13 #ifndef MLPACK_METHODS_NEIGHBOR_SEARCH_NEIGHBOR_SEARCH_IMPL_HPP 14 #define MLPACK_METHODS_NEIGHBOR_SEARCH_NEIGHBOR_SEARCH_IMPL_HPP 25 template<
typename TreeType,
typename MatType>
28 std::vector<size_t>& oldFromNew,
29 typename std::enable_if_t<
33 return new TreeType(std::forward<MatType>(dataset), oldFromNew);
37 template<
typename TreeType,
typename MatType>
40 const std::vector<size_t>& ,
41 const typename std::enable_if_t<
45 return new TreeType(std::forward<MatType>(dataset));
49 template<
typename SortPolicy,
52 template<
typename TreeMetricType,
53 typename TreeStatType,
54 typename TreeMatType>
class TreeType,
55 template<typename> class DualTreeTraversalType,
56 template<typename> class SingleTreeTraversalType>
57 NeighborSearch<SortPolicy, MetricType, MatType, TreeType, DualTreeTraversalType,
58 SingleTreeTraversalType>::NeighborSearch(MatType referenceSetIn,
59 const NeighborSearchMode mode,
61 const MetricType metric) :
62 referenceTree(mode == NAIVE_MODE ? NULL :
63 BuildTree<Tree>(std::move(referenceSetIn), oldFromNewReferences)),
64 referenceSet(mode == NAIVE_MODE ? new MatType(std::move(referenceSetIn)) :
65 &referenceTree->Dataset()),
74 throw std::invalid_argument(
"epsilon must be non-negative");
78 template<
typename SortPolicy,
81 template<
typename TreeMetricType,
82 typename TreeStatType,
83 typename TreeMatType>
class TreeType,
84 template<typename> class DualTreeTraversalType,
85 template<typename> class SingleTreeTraversalType>
86 NeighborSearch<SortPolicy, MetricType, MatType, TreeType, DualTreeTraversalType,
87 SingleTreeTraversalType>::NeighborSearch(Tree referenceTree,
88 const NeighborSearchMode mode,
90 const MetricType metric) :
91 referenceTree(new Tree(std::move(referenceTree))),
92 referenceSet(&this->referenceTree->Dataset()),
101 throw std::invalid_argument(
"epsilon must be non-negative");
105 template<
typename SortPolicy,
108 template<
typename TreeMetricType,
109 typename TreeStatType,
110 typename TreeMatType>
class TreeType,
111 template<typename> class DualTreeTraversalType,
112 template<typename> class SingleTreeTraversalType>
113 NeighborSearch<SortPolicy, MetricType, MatType, TreeType, DualTreeTraversalType,
114 SingleTreeTraversalType>::NeighborSearch(const NeighborSearchMode mode,
115 const double epsilon,
116 const MetricType metric) :
118 referenceSet(mode == NAIVE_MODE ? new MatType() : NULL),
124 treeNeedsReset(false)
127 throw std::invalid_argument(
"epsilon must be non-negative");
130 if (mode != NAIVE_MODE)
132 referenceTree = BuildTree<Tree>(std::move(arma::mat()),
133 oldFromNewReferences);
134 referenceSet = &referenceTree->Dataset();
139 template<
typename SortPolicy,
142 template<
typename TreeMetricType,
143 typename TreeStatType,
144 typename TreeMatType>
class TreeType,
145 template<typename> class DualTreeTraversalType,
146 template<typename> class SingleTreeTraversalType>
147 NeighborSearch<SortPolicy, MetricType, MatType, TreeType, DualTreeTraversalType,
148 SingleTreeTraversalType>::NeighborSearch(const NeighborSearch& other) :
149 oldFromNewReferences(other.oldFromNewReferences),
150 referenceTree(other.referenceTree ? new Tree(*other.referenceTree) : NULL),
151 referenceSet(other.referenceTree ? &referenceTree->Dataset() :
152 new MatType(*other.referenceSet)),
153 searchMode(other.searchMode),
154 epsilon(other.epsilon),
155 metric(other.metric),
156 baseCases(other.baseCases),
157 scores(other.scores),
158 treeNeedsReset(false)
164 template<
typename SortPolicy,
167 template<
typename TreeMetricType,
168 typename TreeStatType,
169 typename TreeMatType>
class TreeType,
170 template<typename> class DualTreeTraversalType,
171 template<typename> class SingleTreeTraversalType>
172 NeighborSearch<SortPolicy, MetricType, MatType, TreeType, DualTreeTraversalType,
173 SingleTreeTraversalType>::NeighborSearch(NeighborSearch&& other) :
174 oldFromNewReferences(std::move(other.oldFromNewReferences)),
175 referenceTree(other.referenceTree),
176 referenceSet(other.referenceSet),
177 searchMode(other.searchMode),
178 epsilon(other.epsilon),
179 metric(std::move(other.metric)),
180 baseCases(other.baseCases),
181 scores(other.scores),
182 treeNeedsReset(other.treeNeedsReset)
185 other.referenceTree = BuildTree<Tree>(std::move(MatType()),
186 other.oldFromNewReferences);
187 other.referenceSet = &other.referenceTree->Dataset();
188 other.searchMode = DUAL_TREE_MODE,
192 other.treeNeedsReset =
false;
196 template<
typename SortPolicy,
199 template<
typename TreeMetricType,
200 typename TreeStatType,
201 typename TreeMatType>
class TreeType,
202 template<typename> class DualTreeTraversalType,
203 template<typename> class SingleTreeTraversalType>
204 NeighborSearch<SortPolicy,
208 DualTreeTraversalType,
209 SingleTreeTraversalType>&
210 NeighborSearch<SortPolicy,
214 DualTreeTraversalType,
215 SingleTreeTraversalType>::operator=(
const NeighborSearch& other)
222 delete referenceTree;
226 oldFromNewReferences = other.oldFromNewReferences;
227 referenceTree = other.referenceTree ?
new Tree(*other.referenceTree) : NULL;
228 referenceSet = other.referenceTree ? &referenceTree->Dataset() :
229 new MatType(*other.referenceSet);
230 searchMode = other.searchMode;
231 epsilon = other.epsilon;
232 metric = other.metric;
233 baseCases = other.baseCases;
234 scores = other.scores;
235 treeNeedsReset =
false;
239 template<
typename SortPolicy,
242 template<
typename TreeMetricType,
243 typename TreeStatType,
244 typename TreeMatType>
class TreeType,
245 template<typename> class DualTreeTraversalType,
246 template<typename> class SingleTreeTraversalType>
247 NeighborSearch<SortPolicy,
251 DualTreeTraversalType,
252 SingleTreeTraversalType>&
253 NeighborSearch<SortPolicy,
257 DualTreeTraversalType,
258 SingleTreeTraversalType>::operator=(NeighborSearch&& other)
265 delete referenceTree;
269 oldFromNewReferences = std::move(other.oldFromNewReferences);
270 referenceTree = other.referenceTree;
271 referenceSet = other.referenceSet;
272 searchMode = other.searchMode;
273 epsilon = other.epsilon;
274 metric = other.metric;
275 baseCases = other.baseCases;
276 scores = other.scores;
277 treeNeedsReset = other.treeNeedsReset;
280 if (!other.referenceTree)
281 delete other.referenceSet;
283 other.referenceTree = BuildTree<Tree>(std::move(arma::mat()),
284 other.oldFromNewReferences);
285 other.referenceSet = &other.referenceTree->Dataset();
286 other.searchMode = DUAL_TREE_MODE,
290 other.treeNeedsReset =
false;
294 template<
typename SortPolicy,
297 template<
typename TreeMetricType,
298 typename TreeStatType,
299 typename TreeMatType>
class TreeType,
300 template<typename> class DualTreeTraversalType,
301 template<typename> class SingleTreeTraversalType>
302 NeighborSearch<SortPolicy, MetricType, MatType, TreeType, DualTreeTraversalType,
303 SingleTreeTraversalType>::~NeighborSearch()
306 delete referenceTree;
311 template<
typename SortPolicy,
314 template<
typename TreeMetricType,
315 typename TreeStatType,
316 typename TreeMatType>
class TreeType,
317 template<typename> class DualTreeTraversalType,
318 template<typename> class SingleTreeTraversalType>
319 void NeighborSearch<SortPolicy, MetricType, MatType, TreeType,
320 DualTreeTraversalType, SingleTreeTraversalType>::
Train(MatType referenceSetIn)
325 oldFromNewReferences.clear();
326 delete referenceTree;
327 referenceTree = NULL;
335 if (searchMode != NAIVE_MODE)
337 referenceTree = BuildTree<Tree>(std::move(referenceSetIn),
338 oldFromNewReferences);
339 referenceSet = &referenceTree->Dataset();
343 referenceSet =
new MatType(std::move(referenceSetIn));
347 template<
typename SortPolicy,
350 template<
typename TreeMetricType,
351 typename TreeStatType,
352 typename TreeMatType>
class TreeType,
353 template<typename> class DualTreeTraversalType,
354 template<typename> class SingleTreeTraversalType>
355 void NeighborSearch<SortPolicy, MetricType, MatType, TreeType,
356 DualTreeTraversalType, SingleTreeTraversalType>::
Train(Tree referenceTree)
358 if (searchMode == NAIVE_MODE)
359 throw std::invalid_argument(
"cannot train on given reference tree when " 360 "naive search (without trees) is desired");
362 if (this->referenceTree)
364 oldFromNewReferences.clear();
365 delete this->referenceTree;
369 delete this->referenceSet;
372 this->referenceTree =
new Tree(std::move(referenceTree));
373 this->referenceSet = &this->referenceTree->Dataset();
380 template<
typename SortPolicy,
383 template<
typename TreeMetricType,
384 typename TreeStatType,
385 typename TreeMatType>
class TreeType,
386 template<typename> class DualTreeTraversalType,
387 template<typename> class SingleTreeTraversalType>
388 void NeighborSearch<SortPolicy, MetricType, MatType, TreeType,
389 DualTreeTraversalType, SingleTreeTraversalType>::Search(
390 const MatType& querySet,
392 arma::Mat<size_t>& neighbors,
393 arma::mat& distances)
395 if (k > referenceSet->n_cols)
397 std::stringstream ss;
398 ss <<
"Requested value of k (" << k <<
") is greater than the number of " 399 <<
"points in the reference set (" << referenceSet->n_cols <<
")";
400 throw std::invalid_argument(ss.str());
409 std::vector<size_t> oldFromNewQueries;
415 arma::Mat<size_t>* neighborPtr = &neighbors;
416 arma::mat* distancePtr = &distances;
421 if (searchMode == DUAL_TREE_MODE)
423 distancePtr =
new arma::mat;
424 neighborPtr =
new arma::Mat<size_t>;
426 else if (!oldFromNewReferences.empty())
427 neighborPtr =
new arma::Mat<size_t>;
431 neighborPtr->set_size(k, querySet.n_cols);
432 distancePtr->set_size(k, querySet.n_cols);
441 RuleType rules(*referenceSet, querySet, k, metric, epsilon);
444 for (
size_t i = 0; i < querySet.n_cols; ++i)
445 for (
size_t j = 0; j < referenceSet->n_cols; ++j)
446 rules.BaseCase(i, j);
448 baseCases += querySet.n_cols * referenceSet->n_cols;
450 rules.GetResults(*neighborPtr, *distancePtr);
453 case SINGLE_TREE_MODE:
456 RuleType rules(*referenceSet, querySet, k, metric, epsilon);
459 SingleTreeTraversalType<RuleType> traverser(rules);
462 for (
size_t i = 0; i < querySet.n_cols; ++i)
463 traverser.Traverse(i, *referenceTree);
465 scores += rules.Scores();
466 baseCases += rules.BaseCases();
468 Log::Info << rules.Scores() <<
" node combinations were scored." 470 Log::Info << rules.BaseCases() <<
" base cases were calculated." 473 rules.GetResults(*neighborPtr, *distancePtr);
481 Tree* queryTree = BuildTree<Tree>(querySet, oldFromNewQueries);
486 RuleType rules(*referenceSet, queryTree->Dataset(), k, metric, epsilon);
489 DualTreeTraversalType<RuleType> traverser(rules);
491 traverser.Traverse(*queryTree, *referenceTree);
493 scores += rules.Scores();
494 baseCases += rules.BaseCases();
496 Log::Info << rules.Scores() <<
" node combinations were scored." 498 Log::Info << rules.BaseCases() <<
" base cases were calculated." 501 rules.GetResults(*neighborPtr, *distancePtr);
506 case GREEDY_SINGLE_TREE_MODE:
509 RuleType rules(*referenceSet, querySet, k, metric);
515 for (
size_t i = 0; i < querySet.n_cols; ++i)
516 traverser.
Traverse(i, *referenceTree);
518 scores += rules.Scores();
519 baseCases += rules.BaseCases();
521 Log::Info << rules.Scores() <<
" node combinations were scored." 523 Log::Info << rules.BaseCases() <<
" base cases were calculated." 526 rules.GetResults(*neighborPtr, *distancePtr);
536 if (searchMode == DUAL_TREE_MODE && !oldFromNewReferences.empty())
539 neighbors.set_size(k, querySet.n_cols);
540 distances.set_size(k, querySet.n_cols);
542 for (
size_t i = 0; i < distances.n_cols; ++i)
545 distances.col(oldFromNewQueries[i]) = distancePtr->col(i);
548 for (
size_t j = 0; j < distances.n_rows; ++j)
550 neighbors(j, oldFromNewQueries[i]) =
551 oldFromNewReferences[(*neighborPtr)(j, i)];
559 else if (searchMode == DUAL_TREE_MODE)
562 neighbors.set_size(k, querySet.n_cols);
563 distances.set_size(k, querySet.n_cols);
565 for (
size_t i = 0; i < distances.n_cols; ++i)
568 const size_t queryMapping = oldFromNewQueries[i];
569 distances.col(queryMapping) = distancePtr->col(i);
570 neighbors.col(queryMapping) = neighborPtr->col(i);
577 else if (!oldFromNewReferences.empty())
580 neighbors.set_size(k, querySet.n_cols);
583 for (
size_t i = 0; i < neighbors.n_cols; ++i)
584 for (
size_t j = 0; j < neighbors.n_rows; ++j)
585 neighbors(j, i) = oldFromNewReferences[(*neighborPtr)(j, i)];
593 template<
typename SortPolicy,
596 template<
typename TreeMetricType,
597 typename TreeStatType,
598 typename TreeMatType>
class TreeType,
599 template<typename> class DualTreeTraversalType,
600 template<typename> class SingleTreeTraversalType>
601 void NeighborSearch<SortPolicy, MetricType, MatType, TreeType,
602 DualTreeTraversalType, SingleTreeTraversalType>::Search(
605 arma::Mat<size_t>& neighbors,
606 arma::mat& distances,
609 if (k > referenceSet->n_cols)
611 std::stringstream ss;
612 ss <<
"Requested value of k (" << k <<
") is greater than the number of " 613 <<
"points in the reference set (" << referenceSet->n_cols <<
")";
614 throw std::invalid_argument(ss.str());
618 if (searchMode != DUAL_TREE_MODE)
619 throw std::invalid_argument(
"cannot call NeighborSearch::Search() with a " 620 "query tree when naive or singleMode are set to true");
628 const MatType& querySet = queryTree.Dataset();
631 arma::Mat<size_t>* neighborPtr = &neighbors;
633 if (!oldFromNewReferences.empty() &&
635 neighborPtr =
new arma::Mat<size_t>;
637 neighborPtr->set_size(k, querySet.n_cols);
638 distances.set_size(k, querySet.n_cols);
642 RuleType rules(*referenceSet, querySet, k, metric, epsilon, sameSet);
645 DualTreeTraversalType<RuleType> traverser(rules);
646 traverser.Traverse(queryTree, *referenceTree);
648 scores += rules.Scores();
649 baseCases += rules.BaseCases();
651 Log::Info << rules.Scores() <<
" node combinations were scored." << std::endl;
652 Log::Info << rules.BaseCases() <<
" base cases were calculated." << std::endl;
654 rules.GetResults(*neighborPtr, distances);
656 Log::Info << rules.Scores() <<
" node combinations were scored.\n";
657 Log::Info << rules.BaseCases() <<
" base cases were calculated.\n";
662 if (!oldFromNewReferences.empty() &&
666 neighbors.set_size(k, querySet.n_cols);
669 for (
size_t i = 0; i < neighbors.n_cols; ++i)
670 for (
size_t j = 0; j < neighbors.n_rows; ++j)
671 neighbors(j, i) = oldFromNewReferences[(*neighborPtr)(j, i)];
678 template<
typename SortPolicy,
681 template<
typename TreeMetricType,
682 typename TreeStatType,
683 typename TreeMatType>
class TreeType,
684 template<typename> class DualTreeTraversalType,
685 template<typename> class SingleTreeTraversalType>
686 void NeighborSearch<SortPolicy, MetricType, MatType, TreeType,
687 DualTreeTraversalType, SingleTreeTraversalType>::Search(
689 arma::Mat<size_t>& neighbors,
690 arma::mat& distances)
692 if (k > referenceSet->n_cols)
694 std::stringstream ss;
695 ss <<
"Requested value of k (" << k <<
") is greater than the number of " 696 <<
"points in the reference set (" << referenceSet->n_cols <<
")";
697 throw std::invalid_argument(ss.str());
699 if (k == referenceSet->n_cols)
701 std::stringstream ss;
702 ss <<
"Requested value of k (" << k <<
") is equal to the number of " 703 <<
"points in the reference set (" << referenceSet->n_cols <<
") and " 704 <<
"no query set has been provided.";
705 throw std::invalid_argument(ss.str());
713 arma::Mat<size_t>* neighborPtr = &neighbors;
714 arma::mat* distancePtr = &distances;
716 if (!oldFromNewReferences.empty() &&
720 distancePtr =
new arma::mat;
721 neighborPtr =
new arma::Mat<size_t>;
725 neighborPtr->set_size(k, referenceSet->n_cols);
726 distancePtr->set_size(k, referenceSet->n_cols);
730 RuleType rules(*referenceSet, *referenceSet, k, metric, epsilon,
738 for (
size_t i = 0; i < referenceSet->n_cols; ++i)
739 for (
size_t j = 0; j < referenceSet->n_cols; ++j)
740 rules.BaseCase(i, j);
742 baseCases += referenceSet->n_cols * referenceSet->n_cols;
745 case SINGLE_TREE_MODE:
748 SingleTreeTraversalType<RuleType> traverser(rules);
751 for (
size_t i = 0; i < referenceSet->n_cols; ++i)
752 traverser.Traverse(i, *referenceTree);
754 scores += rules.Scores();
755 baseCases += rules.BaseCases();
757 Log::Info << rules.Scores() <<
" node combinations were scored." 759 Log::Info << rules.BaseCases() <<
" base cases were calculated." 769 std::stack<Tree*> nodes;
770 nodes.push(referenceTree);
771 while (!nodes.empty())
773 Tree* node = nodes.top();
777 node->Stat().Reset();
780 for (
size_t i = 0; i < node->NumChildren(); ++i)
781 nodes.push(&node->Child(i));
786 DualTreeTraversalType<RuleType> traverser(rules);
792 Tree queryTree(*referenceSet);
793 traverser.Traverse(queryTree, *referenceTree);
797 traverser.Traverse(*referenceTree, *referenceTree);
799 treeNeedsReset =
true;
802 scores += rules.Scores();
803 baseCases += rules.BaseCases();
805 Log::Info << rules.Scores() <<
" node combinations were scored." 807 Log::Info << rules.BaseCases() <<
" base cases were calculated." 811 treeNeedsReset =
true;
814 case GREEDY_SINGLE_TREE_MODE:
820 for (
size_t i = 0; i < referenceSet->n_cols; ++i)
821 traverser.
Traverse(i, *referenceTree);
823 scores += rules.Scores();
824 baseCases += rules.BaseCases();
826 Log::Info << rules.Scores() <<
" node combinations were scored." 828 Log::Info << rules.BaseCases() <<
" base cases were calculated." 834 rules.GetResults(*neighborPtr, *distancePtr);
839 if (!oldFromNewReferences.empty() &&
842 neighbors.set_size(k, referenceSet->n_cols);
843 distances.set_size(k, referenceSet->n_cols);
845 for (
size_t i = 0; i < distances.n_cols; ++i)
848 const size_t refMapping = oldFromNewReferences[i];
849 distances.col(refMapping) = distancePtr->col(i);
852 for (
size_t j = 0; j < distances.n_rows; ++j)
853 neighbors(j, refMapping) = oldFromNewReferences[(*neighborPtr)(j, i)];
863 template<
typename SortPolicy,
866 template<
typename TreeMetricType,
867 typename TreeStatType,
868 typename TreeMatType>
class TreeType,
869 template<typename> class DualTreeTraversalType,
870 template<typename> class SingleTreeTraversalType>
871 double NeighborSearch<SortPolicy, MetricType, MatType, TreeType,
872 DualTreeTraversalType, SingleTreeTraversalType>::EffectiveError(
873 arma::mat& foundDistances,
874 arma::mat& realDistances)
876 if (foundDistances.n_rows != realDistances.n_rows ||
877 foundDistances.n_cols != realDistances.n_cols)
878 throw std::invalid_argument(
"matrices provided must have equal size");
880 double effectiveError = 0;
883 for (
size_t i = 0; i < foundDistances.n_elem; ++i)
885 if (realDistances(i) != 0 &&
886 foundDistances(i) != SortPolicy::WorstDistance())
888 effectiveError += fabs(foundDistances(i) - realDistances(i)) /
895 effectiveError /= numCases;
897 return effectiveError;
901 template<
typename SortPolicy,
904 template<
typename TreeMetricType,
905 typename TreeStatType,
906 typename TreeMatType>
class TreeType,
907 template<typename> class DualTreeTraversalType,
908 template<typename> class SingleTreeTraversalType>
909 double NeighborSearch<SortPolicy, MetricType, MatType, TreeType,
910 DualTreeTraversalType, SingleTreeTraversalType>::Recall(
911 arma::Mat<size_t>& foundNeighbors,
912 arma::Mat<size_t>& realNeighbors)
914 if (foundNeighbors.n_rows != realNeighbors.n_rows ||
915 foundNeighbors.n_cols != realNeighbors.n_cols)
916 throw std::invalid_argument(
"matrices provided must have equal size");
919 for (
size_t col = 0; col < foundNeighbors.n_cols; ++col)
920 for (
size_t row = 0; row < foundNeighbors.n_rows; ++row)
921 for (
size_t nei = 0; nei < realNeighbors.n_rows; ++nei)
922 if (foundNeighbors(row, col) == realNeighbors(nei, col))
928 return ((
double) found) / realNeighbors.n_elem;
932 template<
typename SortPolicy,
935 template<
typename TreeMetricType,
936 typename TreeStatType,
937 typename TreeMatType>
class TreeType,
938 template<typename> class DualTreeTraversalType,
939 template<typename> class SingleTreeTraversalType>
940 template<typename Archive>
941 void NeighborSearch<SortPolicy, MetricType, MatType, TreeType,
942 DualTreeTraversalType, SingleTreeTraversalType>::serialize(
943 Archive& ar, const uint32_t )
946 ar(CEREAL_NVP(searchMode));
947 ar(CEREAL_NVP(treeNeedsReset));
951 if (searchMode == NAIVE_MODE)
954 if (cereal::is_loading<Archive>() && referenceSet)
960 ar(CEREAL_NVP(metric));
963 if (cereal::is_loading<Archive>())
966 delete referenceTree;
968 referenceTree = NULL;
969 oldFromNewReferences.clear();
975 if (cereal::is_loading<Archive>() && referenceTree)
977 delete referenceTree;
981 ar(CEREAL_NVP(oldFromNewReferences));
985 if (cereal::is_loading<Archive>())
987 referenceSet = &referenceTree->Dataset();
988 metric = referenceTree->Metric();
993 if (cereal::is_loading<Archive>())
static void Start(const std::string &name)
Start the given timer.
Definition: timers.cpp:28
Definition: is_spill_tree.hpp:21
Linear algebra utility functions, generally performed on matrices or vectors.
Definition: cv.hpp:1
void Traverse(const size_t queryIndex, TreeType &referenceNode)
Traverse the tree with the given point.
Definition: greedy_single_tree_traverser_impl.hpp:31
The core includes that mlpack expects; standard C++ includes and Armadillo.
Definition: greedy_single_tree_traverser.hpp:23
The NeighborSearchRules class is a template helper class used by NeighborSearch class when performing...
Definition: neighbor_search_rules.hpp:35
Definition: hmm_train_main.cpp:300
static void Stop(const std::string &name)
Stop the given timer.
Definition: timers.cpp:36
The TreeTraits class provides compile-time information on the characteristics of a given tree type...
Definition: tree_traits.hpp:77
static MLPACK_EXPORT util::PrefixedOutStream Info
Prints informational messages if –verbose is specified, prefixed with [INFO ].
Definition: log.hpp:84
#define CEREAL_POINTER(T)
Cereal does not support the serialization of raw pointer.
Definition: pointer_wrapper.hpp:96
Definition of IsSpillTree.