diff --git a/src/mlpack/methods/hoeffding_trees/hoeffding_tree.hpp b/src/mlpack/methods/hoeffding_trees/hoeffding_tree.hpp index 488048f4e6..b58d97a423 100644 --- a/src/mlpack/methods/hoeffding_trees/hoeffding_tree.hpp +++ b/src/mlpack/methods/hoeffding_trees/hoeffding_tree.hpp @@ -155,6 +155,27 @@ class HoeffdingTree */ HoeffdingTree(const HoeffdingTree& other); + /** + * Move another tree. + * + * @param other Tree to move. + */ + HoeffdingTree(HoeffdingTree&& other); + + /** + * Copy assignment operator. + * + * @param other Tree to copy. + */ + HoeffdingTree& operator=(const HoeffdingTree& other); + + /** + * Move assignment operator. + * + * @param other Tree to move. + */ + HoeffdingTree& operator=(HoeffdingTree&& other); + /** * Clean up memory. */ diff --git a/src/mlpack/methods/hoeffding_trees/hoeffding_tree_impl.hpp b/src/mlpack/methods/hoeffding_trees/hoeffding_tree_impl.hpp index e6172f8324..f7e8bdd830 100644 --- a/src/mlpack/methods/hoeffding_trees/hoeffding_tree_impl.hpp +++ b/src/mlpack/methods/hoeffding_trees/hoeffding_tree_impl.hpp @@ -224,6 +224,117 @@ HoeffdingTree:: } } +// Move constructor. +template class NumericSplitType, + template class CategoricalSplitType> +HoeffdingTree:: + HoeffdingTree(HoeffdingTree&& other) : + numericSplits(std::move(other.numericSplits)), + categoricalSplits(std::move(other.categoricalSplits)), + dimensionMappings(other.dimensionMappings), + ownsMappings(true), + numSamples(other.numSamples), + numClasses(other.numClasses), + maxSamples(other.maxSamples), + checkInterval(other.checkInterval), + minSamples(other.minSamples), + datasetInfo(other.datasetInfo), + ownsInfo(true), + successProbability(other.successProbability), + splitDimension(other.splitDimension), + majorityClass(other.majorityClass), + majorityProbability(other.majorityProbability), + categoricalSplit(std::move(other.categoricalSplit)), + numericSplit(std::move(other.numericSplit)) +{ + // Remove pointers. + other.dimensionMappings = nullptr; + other.datasetInfo = nullptr; +} + +// Copy assignment operator. +template class NumericSplitType, + template class CategoricalSplitType> +HoeffdingTree& + HoeffdingTree:: + operator=(const HoeffdingTree& other) : +{ + if (this != &other) + { + numericSplits = other.numericSplits; + categoricalSplits = other.categoricalSplits; + dimensionMappings = new std::unordered_map>(*other.dimensionMappings); + ownsMappings = true; + numSamples = other.numSamples; + numClasses = other.numClasses; + maxSamples = other.maxSamples; + checkInterval = other.checkInterval; + minSamples = other.minSamples; + datasetInfo = new data::DatasetInfo(*other.datasetInfo); + ownsInfo = true; + successProbability = other.successProbability; + splitDimension = other.splitDimension; + majorityClass = other.majorityClass; + majorityProbability = other.majorityProbability; + categoricalSplit = other.categoricalSplit; + numericSplit = other.numericSplit; + + // Copy each of the children. + for (size_t i = 0; i < other.children.size(); ++i) + { + children.push_back(new HoeffdingTree(*other.children[i])); + + // Delete copied datasetInfo and dimension mappings. + delete children[i]->datasetInfo; + children[i]->datasetInfo = this->datasetInfo; + children[i]->ownsInfo = false; + + delete children[i]->dimensionMappings; + children[i]->dimensionMappings = this->dimensionMappings; + children[i]->ownsMappings = false; + } + } + return *this; +} + +// Move assignment operator. +template class NumericSplitType, + template class CategoricalSplitType> +HoeffdingTree& + HoeffdingTree:: + operator=(HoeffdingTree&& other) : +{ + if (this != &other) + { + numericSplits = std::move(other.numericSplits); + categoricalSplits = std::move(other.categoricalSplits); + dimensionMappings = other.dimensionMappings; + ownsMappings = true; + numSamples = other.numSamples; + numClasses = other.numClasses; + maxSamples = other.maxSamples; + checkInterval = other.checkInterval; + minSamples = other.minSamples; + datasetInfo = other.datasetInfo; + ownsInfo = true; + successProbability = other.successProbability; + splitDimension = other.splitDimension; + majorityClass = other.majorityClass; + majorityProbability = other.majorityProbability; + categoricalSplit = std::move(other.categoricalSplit); + numericSplit = std::move(other.numericSplit); + // Remove pointers. + other.dimensionMappings = nullptr; + other.datasetInfo = nullptr; + } + return *this; +} + + template class NumericSplitType, template class CategoricalSplitType> diff --git a/src/mlpack/methods/hoeffding_trees/hoeffding_tree_model.cpp b/src/mlpack/methods/hoeffding_trees/hoeffding_tree_model.cpp index d35970dd5b..2dfe857edf 100644 --- a/src/mlpack/methods/hoeffding_trees/hoeffding_tree_model.cpp +++ b/src/mlpack/methods/hoeffding_trees/hoeffding_tree_model.cpp @@ -62,53 +62,57 @@ HoeffdingTreeModel::HoeffdingTreeModel(HoeffdingTreeModel&& other) : HoeffdingTreeModel& HoeffdingTreeModel::operator=( const HoeffdingTreeModel& other) { - // Clear this model. - delete giniHoeffdingTree; - delete giniBinaryTree; - delete infoHoeffdingTree; - delete infoBinaryTree; + if (this != &other) + { + // Clear this model. + delete giniHoeffdingTree; + delete giniBinaryTree; + delete infoHoeffdingTree; + delete infoBinaryTree; - giniHoeffdingTree = NULL; - giniBinaryTree = NULL; - infoHoeffdingTree = NULL; - infoBinaryTree = NULL; - - // Create the right tree. - type = other.type; - if (other.giniHoeffdingTree && (type == GINI_HOEFFDING)) - giniHoeffdingTree = new GiniHoeffdingTreeType(*other.giniHoeffdingTree); - else if (other.giniBinaryTree && (type == GINI_BINARY)) - giniBinaryTree = new GiniBinaryTreeType(*other.giniBinaryTree); - else if (other.infoHoeffdingTree && (type == INFO_HOEFFDING)) - infoHoeffdingTree = new InfoHoeffdingTreeType(*other.infoHoeffdingTree); - else if (other.infoBinaryTree && (type == INFO_BINARY)) - infoBinaryTree = new InfoBinaryTreeType(*other.infoBinaryTree); + giniHoeffdingTree = NULL; + giniBinaryTree = NULL; + infoHoeffdingTree = NULL; + infoBinaryTree = NULL; + // Create the right tree. + type = other.type; + if (other.giniHoeffdingTree && (type == GINI_HOEFFDING)) + giniHoeffdingTree = new GiniHoeffdingTreeType(*other.giniHoeffdingTree); + else if (other.giniBinaryTree && (type == GINI_BINARY)) + giniBinaryTree = new GiniBinaryTreeType(*other.giniBinaryTree); + else if (other.infoHoeffdingTree && (type == INFO_HOEFFDING)) + infoHoeffdingTree = new InfoHoeffdingTreeType(*other.infoHoeffdingTree); + else if (other.infoBinaryTree && (type == INFO_BINARY)) + infoBinaryTree = new InfoBinaryTreeType(*other.infoBinaryTree); + } return *this; } // Move operator. HoeffdingTreeModel& HoeffdingTreeModel::operator=(HoeffdingTreeModel&& other) { - // Clear this model. - delete giniHoeffdingTree; - delete giniBinaryTree; - delete infoHoeffdingTree; - delete infoBinaryTree; + if (this != &other) + { + // Clear this model. + delete giniHoeffdingTree; + delete giniBinaryTree; + delete infoHoeffdingTree; + delete infoBinaryTree; - type = other.type; - giniHoeffdingTree = other.giniHoeffdingTree; - giniBinaryTree = other.giniBinaryTree; - infoHoeffdingTree = other.infoHoeffdingTree; - infoBinaryTree = other.infoBinaryTree; - - // Clear the other model. - other.type = GINI_HOEFFDING; - other.giniHoeffdingTree = NULL; - other.giniBinaryTree = NULL; - other.infoHoeffdingTree = NULL; - other.infoBinaryTree = NULL; + type = other.type; + giniHoeffdingTree = other.giniHoeffdingTree; + giniBinaryTree = other.giniBinaryTree; + infoHoeffdingTree = other.infoHoeffdingTree; + infoBinaryTree = other.infoBinaryTree; + // Clear the other model. + other.type = GINI_HOEFFDING; + other.giniHoeffdingTree = NULL; + other.giniBinaryTree = NULL; + other.infoHoeffdingTree = NULL; + other.infoBinaryTree = NULL; + } return *this; } diff --git a/src/mlpack/methods/kde/kde.hpp b/src/mlpack/methods/kde/kde.hpp index 448d32dd84..8885c2e894 100644 --- a/src/mlpack/methods/kde/kde.hpp +++ b/src/mlpack/methods/kde/kde.hpp @@ -140,11 +140,16 @@ class KDE /** * Copy a KDE model. * - * Use std::move if the object to copy is no longer needed. + * @param other KDE model to copy. + */ + KDE& operator=(const KDE& other); + + /** + * Move a KDE model. * * @param other KDE model to copy. */ - KDE& operator=(KDE other); + KDE& operator=(KDE&& other); /** * Destroy the KDE object. If this object created any trees, they will be diff --git a/src/mlpack/methods/kde/kde_impl.hpp b/src/mlpack/methods/kde/kde_impl.hpp index b48190e686..054c02119d 100644 --- a/src/mlpack/methods/kde/kde_impl.hpp +++ b/src/mlpack/methods/kde/kde_impl.hpp @@ -190,31 +190,95 @@ KDE:: -operator=(KDE other) +operator=(const KDE& other) { - // Clean memory. - if (ownsReferenceTree) + if (this != &other) { - delete referenceTree; - delete oldFromNewReferences; + // Clean memory. + if (ownsReferenceTree) + { + delete referenceTree; + delete oldFromNewReferences; + } + kernel = KernelType(other.kernel); + metric = MetricType(other.metric); + relError = other.relError; + absError = other.absError; + ownsReferenceTree = other.ownsReferenceTree; + trained = other.trained; + mode = other.mode; + monteCarlo = other.monteCarlo; + mcProb = other.mcProb; + initialSampleSize = other.initialSampleSize; + mcEntryCoef = other.mcEntryCoef; + mcBreakCoef = other.mcBreakCoef; + if (trained) + { + if (ownsReferenceTree) + { + oldFromNewReferences = + new std::vector(*other.oldFromNewReferences); + referenceTree = new Tree(*other.referenceTree); + } + else + { + oldFromNewReferences = other.oldFromNewReferences; + referenceTree = other.referenceTree; + } + } } + return *this; +} - // Move the other object. - this->kernel = std::move(other.kernel); - this->metric = std::move(other.metric); - this->referenceTree = std::move(other.referenceTree); - this->oldFromNewReferences = std::move(other.oldFromNewReferences); - this->relError = other.relError; - this->absError = other.absError; - this->ownsReferenceTree = other.ownsReferenceTree; - this->trained = other.trained; - this->mode = other.mode; - this->monteCarlo = other.monteCarlo; - this->mcProb = other.mcProb; - this->initialSampleSize = other.initialSampleSize; - this->mcEntryCoef = other.mcEntryCoef; - this->mcBreakCoef = other.mcBreakCoef; +template class TreeType, + template class DualTreeTraversalType, + template class SingleTreeTraversalType> +KDE& +KDE:: +operator=(KDE&& other) +{ + if (this != &other) + { + // Clean memory. + if (ownsReferenceTree) + { + delete referenceTree; + delete oldFromNewReferences; + } + // Move the other object. + this->kernel = std::move(other.kernel); + this->metric = std::move(other.metric); + // TODO: This should be: this->referenceTree = other.referenceTree; + this->referenceTree = std::move(other.referenceTree); + // TODO: This should be: this->oldFromNewReferences = other.oldFromNewReferences; + this->oldFromNewReferences = std::move(other.oldFromNewReferences); + this->relError = other.relError; + this->absError = other.absError; + this->ownsReferenceTree = other.ownsReferenceTree; + this->trained = other.trained; + this->mode = other.mode; + this->monteCarlo = other.monteCarlo; + this->mcProb = other.mcProb; + this->initialSampleSize = other.initialSampleSize; + this->mcEntryCoef = other.mcEntryCoef; + this->mcBreakCoef = other.mcBreakCoef; + } return *this; }