diff --git a/docs/CHANGELOG.asciidoc b/docs/CHANGELOG.asciidoc index 72e91d207b..36c0713553 100644 --- a/docs/CHANGELOG.asciidoc +++ b/docs/CHANGELOG.asciidoc @@ -32,6 +32,9 @@ Secure the ML processes by preventing system calls such as fork and exec. The Li Seccomp BPF to intercept system calls and is available in kernels since 3.5. On Windows Job Objects prevent new processes being created and macOS uses the sandbox functionality ({pull}98[#98]) +Fix a bug causing us to under estimate the memory used by shared pointers and reduce the memory consumed +by unnecessary reference counting ({pull}108[#108]) + === Bug Fixes Age seasonal components in proportion to the fraction of values with which they're updated ({pull}88[#88]) diff --git a/include/api/CForecastRunner.h b/include/api/CForecastRunner.h index f678592dd5..ff54659b8c 100644 --- a/include/api/CForecastRunner.h +++ b/include/api/CForecastRunner.h @@ -115,7 +115,7 @@ class API_EXPORT CForecastRunner final : private core::CNonCopyable { using TForecastModelWrapper = model::CForecastDataSink::SForecastModelWrapper; using TForecastResultSeries = model::CForecastDataSink::SForecastResultSeries; using TForecastResultSeriesVec = std::vector; - using TMathsModelPtr = std::shared_ptr; + using TMathsModelPtr = std::unique_ptr; using TStrUSet = boost::unordered_set; diff --git a/include/core/CMemory.h b/include/core/CMemory.h index 4c8cb022b6..6d6f839c2f 100644 --- a/include/core/CMemory.h +++ b/include/core/CMemory.h @@ -287,21 +287,25 @@ class CORE_EXPORT CMemory : private CNonInstantiatable { static std::size_t dynamicSize(const T& t, typename boost::enable_if>::type* = nullptr) { - if (t == nullptr) { - return 0; - } - return staticSize(*t) + dynamicSize(*t); + return t == nullptr ? 0 : staticSize(*t) + dynamicSize(*t); } //! Overload for std::shared_ptr. template static std::size_t dynamicSize(const std::shared_ptr& t) { - if (!t) { + if (t == nullptr) { return 0; } long uc = t.use_count(); - // Round up - return (staticSize(*t) + dynamicSize(*t) + std::size_t(uc - 1)) / uc; + // Note we add on sizeof(long) here to account for the memory + // used by the shared reference count. Also, round up. + return (sizeof(long) + staticSize(*t) + dynamicSize(*t) + std::size_t(uc - 1)) / uc; + } + + //! Overload for std::unique_ptr. + template + static std::size_t dynamicSize(const std::unique_ptr& t) { + return t == nullptr ? 0 : staticSize(*t) + dynamicSize(*t); } //! Overload for boost::array. @@ -703,25 +707,40 @@ class CORE_EXPORT CMemoryDebug : private CNonInstantiatable { static void dynamicSize(const char* name, const std::shared_ptr& t, CMemoryUsage::TMemoryUsagePtr mem) { - if (t) { + if (t != nullptr) { long uc = t.use_count(); // If the pointer is shared by multiple users, each one // might count it, so divide by the number of users. // However, if only 1 user has it, do a full debug. if (uc == 1) { - mem->addItem("shared_ptr", CMemory::staticSize(*t)); + // Note we add on sizeof(long) here to account for + // the memory used by the shared reference count. + mem->addItem("shared_ptr", sizeof(long) + CMemory::staticSize(*t)); dynamicSize(name, *t, mem); } else { std::ostringstream ss; ss << "shared_ptr (x" << uc << ')'; - // Round up - mem->addItem(ss.str(), (CMemory::staticSize(*t) + + // Note we add on sizeof(long) here to account for + // the memory used by the shared reference count. + // Also, round up. + mem->addItem(ss.str(), (sizeof(long) + CMemory::staticSize(*t) + CMemory::dynamicSize(*t) + std::size_t(uc - 1)) / uc); } } } + //! Overload for std::unique_ptr. + template + static void dynamicSize(const char* name, + const std::unique_ptr& t, + CMemoryUsage::TMemoryUsagePtr mem) { + if (t != nullptr) { + mem->addItem("ptr", CMemory::staticSize(*t)); + memory_detail::SDebugMemoryDynamicSize::dispatch(name, *t, mem); + } + } + //! Overload for boost::array. template static void dynamicSize(const char* name, diff --git a/include/maths/CChecksum.h b/include/maths/CChecksum.h index f8da99d94d..55125dd255 100644 --- a/include/maths/CChecksum.h +++ b/include/maths/CChecksum.h @@ -158,13 +158,20 @@ class CChecksumImpl { : CChecksumImpl::value>::dispatch(seed, *target); } - //! Checksum a pointer. + //! Checksum a shared pointer. template static uint64_t dispatch(uint64_t seed, const std::shared_ptr& target) { return !target ? seed : CChecksumImpl::value>::dispatch(seed, *target); } + //! Checksum a unique pointer. + template + static uint64_t dispatch(uint64_t seed, const std::unique_ptr& target) { + return !target ? seed + : CChecksumImpl::value>::dispatch(seed, *target); + } + //! Checksum a pair. template static uint64_t dispatch(uint64_t seed, const std::pair& target) { diff --git a/include/maths/CClusterer.h b/include/maths/CClusterer.h index 8f1b5b2e79..70c7375bef 100644 --- a/include/maths/CClusterer.h +++ b/include/maths/CClusterer.h @@ -125,7 +125,6 @@ class MATHS_EXPORT CClustererTypes { template class CClusterer : public CClustererTypes { public: - using TClustererPtr = std::shared_ptr; using TPointVec = std::vector; using TPointPrecise = typename SPromoted::Type; using TPointPreciseVec = std::vector; diff --git a/include/maths/CClustererStateSerialiser.h b/include/maths/CClustererStateSerialiser.h index faee50eaf2..c2e38867f8 100644 --- a/include/maths/CClustererStateSerialiser.h +++ b/include/maths/CClustererStateSerialiser.h @@ -43,7 +43,7 @@ struct SDistributionRestoreParams; //! to potential competitors. class MATHS_EXPORT CClustererStateSerialiser { public: - using TClusterer1dPtr = std::shared_ptr; + using TClusterer1dPtr = std::unique_ptr; public: //! Construct the appropriate CClusterer sub-class from its state @@ -73,7 +73,7 @@ class MATHS_EXPORT CClustererStateSerialiser { //! \note Sets \p ptr to NULL on failure. template bool operator()(const SDistributionRestoreParams& params, - std::shared_ptr>>& ptr, + std::unique_ptr>>& ptr, core::CStateRestoreTraverser& traverser) { return this->operator()(params, CClustererTypes::CDoNothing(), CClustererTypes::CDoNothing(), ptr, traverser); @@ -87,7 +87,7 @@ class MATHS_EXPORT CClustererStateSerialiser { bool operator()(const SDistributionRestoreParams& params, const CClustererTypes::TSplitFunc& splitFunc, const CClustererTypes::TMergeFunc& mergeFunc, - std::shared_ptr>>& ptr, + std::unique_ptr>>& ptr, core::CStateRestoreTraverser& traverser) { std::size_t numResults(0); diff --git a/include/maths/CModelStateSerialiser.h b/include/maths/CModelStateSerialiser.h index 0d2ef51b64..1c4fdd6233 100644 --- a/include/maths/CModelStateSerialiser.h +++ b/include/maths/CModelStateSerialiser.h @@ -34,7 +34,7 @@ struct SModelRestoreParams; //! compatibility in the future as the classes evolve. class MATHS_EXPORT CModelStateSerialiser { public: - using TModelPtr = std::shared_ptr; + using TModelPtr = std::unique_ptr; public: //! Construct the appropriate CPrior sub-class from its state diff --git a/include/maths/CMultimodalPrior.h b/include/maths/CMultimodalPrior.h index b34d4e7096..9156d7fa3b 100644 --- a/include/maths/CMultimodalPrior.h +++ b/include/maths/CMultimodalPrior.h @@ -49,11 +49,9 @@ namespace maths { //! point of view this is the composite pattern. class MATHS_EXPORT CMultimodalPrior : public CPrior { public: - using TClustererPtr = std::shared_ptr; - using TPriorPtr = std::shared_ptr; + using TClustererPtr = std::unique_ptr; + using TPriorPtr = std::unique_ptr; using TPriorPtrVec = std::vector; - using TPriorPtrVecItr = TPriorPtrVec::iterator; - using TPriorPtrVecCItr = TPriorPtrVec::const_iterator; using TMeanVarAccumulator = CBasicStatistics::SSampleMeanVar::TAccumulator; using TMeanVarAccumulatorVec = std::vector; @@ -80,6 +78,9 @@ class MATHS_EXPORT CMultimodalPrior : public CPrior { double decayRate = 0.0); //! Create from a collection of weights and priors. + //! + //! \note The priors are moved into place clearing the values in \p priors. + //! \note This constructor doesn't support subsequent update of the prior. CMultimodalPrior(maths_t::EDataType dataType, double decayRate, TPriorPtrVec& priors); //! Construct from part of a state document. @@ -320,7 +321,7 @@ class MATHS_EXPORT CMultimodalPrior : public CPrior { CMultimodalPrior* m_Prior; }; - using TMode = SMultimodalPriorMode>; + using TMode = SMultimodalPriorMode; using TModeVec = std::vector; private: diff --git a/include/maths/CMultimodalPriorMode.h b/include/maths/CMultimodalPriorMode.h index ace923875d..c7df92a7aa 100644 --- a/include/maths/CMultimodalPriorMode.h +++ b/include/maths/CMultimodalPriorMode.h @@ -36,6 +36,16 @@ struct SMultimodalPriorMode { SMultimodalPriorMode() : s_Index(0), s_Prior() {} SMultimodalPriorMode(std::size_t index, const PRIOR_PTR& prior) : s_Index(index), s_Prior(prior->clone()) {} + SMultimodalPriorMode(std::size_t index, PRIOR_PTR&& prior) + : s_Index(index), s_Prior(std::move(prior)) {} + SMultimodalPriorMode(SMultimodalPriorMode&& other) + : s_Index(other.s_Index), s_Prior(std::move(other.s_Prior)) {} + SMultimodalPriorMode& operator=(SMultimodalPriorMode&& other) { + s_Index = other.s_Index; + s_Prior = std::move(other.s_Prior); + return *this; + } + SMultimodalPriorMode& operator=(const SMultimodalPriorMode&) = delete; //! Get the weight of this sample. double weight() const { return s_Prior->numberSamples(); } diff --git a/include/maths/CMultivariateMultimodalPrior.h b/include/maths/CMultivariateMultimodalPrior.h index af509bbab3..3b720b5f1c 100644 --- a/include/maths/CMultivariateMultimodalPrior.h +++ b/include/maths/CMultivariateMultimodalPrior.h @@ -32,6 +32,7 @@ #include #include +#include #include #include @@ -50,10 +51,10 @@ namespace multivariate_multimodal_prior_detail { using TSizeDoublePr = std::pair; using TSizeDoublePr3Vec = core::CSmallVector; -using TPriorPtr = std::shared_ptr; using TDouble10Vec1Vec = CMultivariatePrior::TDouble10Vec1Vec; using TDouble10VecWeightsAry1Vec = CMultivariatePrior::TDouble10VecWeightsAry1Vec; -using TMode = SMultimodalPriorMode>; +using TPriorPtr = std::unique_ptr; +using TMode = SMultimodalPriorMode; using TModeVec = std::vector; //! Implementation of a sample joint log marginal likelihood calculation. @@ -134,7 +135,7 @@ class CMultivariateMultimodalPrior : public CMultivariatePrior { using TMatrix = CSymmetricMatrixNxN; using TMatrixVec = std::vector; using TClusterer = CClusterer; - using TClustererPtr = std::shared_ptr; + using TClustererPtr = std::unique_ptr; using TPriorPtrVec = std::vector; // Lift all overloads of into scope. @@ -162,13 +163,13 @@ class CMultivariateMultimodalPrior : public CMultivariatePrior { //! Create from a collection of priors. //! - //! \note The priors are shallow copied. + //! \note The priors are moved into place clearing the values in \p priors. //! \note This constructor doesn't support subsequent update of the prior. CMultivariateMultimodalPrior(maths_t::EDataType dataType, TPriorPtrVec& priors) : CMultivariatePrior(dataType, 0.0) { m_Modes.reserve(priors.size()); for (std::size_t i = 0u; i < priors.size(); ++i) { - m_Modes.emplace_back(i, priors[i]); + m_Modes.emplace_back(i, std::move(priors[i])); } } @@ -425,12 +426,12 @@ class CMultivariateMultimodalPrior : public CMultivariatePrior { for (const auto& mode : m_Modes) { TUnivariatePriorPtrDoublePr prior(mode.s_Prior->univariate(marginalize, condition)); if (prior.first == nullptr) { - return TUnivariatePriorPtrDoublePr(); + return {}; } if (prior.first->isNonInformative()) { continue; } - modes.push_back(prior.first); + modes.push_back(std::move(prior.first)); weights.push_back(prior.second); maxWeight.add(weights.back()); } @@ -444,8 +445,8 @@ class CMultivariateMultimodalPrior : public CMultivariatePrior { modes[i]->numberSamples(weights[i] / Z * modes[i]->numberSamples()); } - return {TUnivariatePriorPtr(new CMultimodalPrior(this->dataType(), - this->decayRate(), modes)), + return {boost::make_unique(this->dataType(), + this->decayRate(), modes), Z > 0.0 ? maxWeight[0] + std::log(Z) : 0.0}; } @@ -465,7 +466,7 @@ class CMultivariateMultimodalPrior : public CMultivariatePrior { const TSizeDoublePr10Vec& condition) const { if (N == 2) { - return TPriorPtrDoublePr(TPriorPtr(this->clone()), 0.0); + return {TPriorPtr(this->clone()), 0.0}; } std::size_t n = m_Modes.size(); @@ -484,7 +485,7 @@ class CMultivariateMultimodalPrior : public CMultivariatePrior { if (prior.first->isNonInformative()) { continue; } - modes.push_back(prior.first); + modes.push_back(std::move(prior.first)); weights.push_back(prior.second); maxWeight.add(weights.back()); } @@ -498,7 +499,7 @@ class CMultivariateMultimodalPrior : public CMultivariatePrior { modes[i]->numberSamples(weights[i] / Z * modes[i]->numberSamples()); } - return {TPriorPtr(new CMultivariateMultimodalPrior<2>(this->dataType(), modes)), + return {boost::make_unique>(this->dataType(), modes), Z > 0.0 ? maxWeight[0] + std::log(Z) : 0.0}; } @@ -905,7 +906,7 @@ class CMultivariateMultimodalPrior : public CMultivariatePrior { // Create the child modes. LOG_TRACE(<< "Creating mode with index " << leftSplitIndex); - modes.emplace_back(leftSplitIndex, m_Prior->m_SeedPrior); + modes.emplace_back(leftSplitIndex, TPriorPtr(m_Prior->m_SeedPrior->clone())); { TPointVec samples; if (!m_Prior->m_Clusterer->sample( @@ -935,7 +936,7 @@ class CMultivariateMultimodalPrior : public CMultivariatePrior { } LOG_TRACE(<< "Creating mode with index " << rightSplitIndex); - modes.emplace_back(rightSplitIndex, m_Prior->m_SeedPrior); + modes.emplace_back(rightSplitIndex, TPriorPtr(m_Prior->m_SeedPrior->clone())); { TPointVec samples; if (!m_Prior->m_Clusterer->sample( @@ -1025,7 +1026,7 @@ class CMultivariateMultimodalPrior : public CMultivariatePrior { MODE_TAG, TMode mode, traverser.traverseSubLevel(boost::bind( &TMode::acceptRestoreTraverser, &mode, boost::cref(params), _1)), - m_Modes.push_back(mode)) + m_Modes.push_back(std::move(mode))) RESTORE_SETUP_TEARDOWN( NUMBER_SAMPLES_TAG, double numberSamples, core::CStringUtils::stringToType(traverser.value(), numberSamples), diff --git a/include/maths/CMultivariateMultimodalPriorFactory.h b/include/maths/CMultivariateMultimodalPriorFactory.h index e9e03d51ea..28ea037362 100644 --- a/include/maths/CMultivariateMultimodalPriorFactory.h +++ b/include/maths/CMultivariateMultimodalPriorFactory.h @@ -25,7 +25,7 @@ struct SDistributionRestoreParams; //! \brief Factory for multivariate multimodal priors. class MATHS_EXPORT CMultivariateMultimodalPriorFactory { public: - using TPriorPtr = std::shared_ptr; + using TPriorPtr = std::unique_ptr; public: //! Create a new non-informative multivariate normal prior. diff --git a/include/maths/CMultivariateNormalConjugate.h b/include/maths/CMultivariateNormalConjugate.h index e85ad90ff6..6c28b77d48 100644 --- a/include/maths/CMultivariateNormalConjugate.h +++ b/include/maths/CMultivariateNormalConjugate.h @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -348,7 +349,7 @@ class CMultivariateNormalConjugate : public CMultivariatePrior { univariate(const TSize10Vec& marginalize, const TSizeDoublePr10Vec& condition) const { if (!this->check(marginalize, condition)) { - return TUnivariatePriorPtrDoublePr(); + return {}; } TSize10Vec i1; @@ -358,7 +359,7 @@ class CMultivariateNormalConjugate : public CMultivariatePrior { << "marginalize '" << core::CContainerPrinter::print(marginalize) << "'" << ", condition '" << core::CContainerPrinter::print(condition) << "'"); - return TUnivariatePriorPtrDoublePr(); + return {}; } maths_t::EDataType dataType = this->dataType(); @@ -378,8 +379,8 @@ class CMultivariateNormalConjugate : public CMultivariatePrior { double m1 = m(i1[0]); double c11 = c(i1[0], i1[0]); if (condition.empty()) { - return {TUnivariatePriorPtr(new CNormalMeanPrecConjugate( - dataType, m1, p, s, c11 * v / 2.0, decayRate)), + return {boost::make_unique( + dataType, m1, p, s, c11 * v / 2.0, decayRate), 0.0}; } @@ -408,14 +409,14 @@ class CMultivariateNormalConjugate : public CMultivariatePrior { LOG_TRACE(<< "mean = " << mean << ", variance = " << variance << ", weight = " << weight); - return {TUnivariatePriorPtr(new CNormalMeanPrecConjugate( - dataType, mean, p, s, variance * v / 2.0, decayRate)), + return {boost::make_unique( + dataType, mean, p, s, variance * v / 2.0, decayRate), weight}; } catch (const std::exception& e) { LOG_ERROR(<< "Failed to get univariate prior: " << e.what()); } - return TUnivariatePriorPtrDoublePr(); + return {}; } //! Compute the bivariate prior marginalizing over the variables @@ -433,16 +434,16 @@ class CMultivariateNormalConjugate : public CMultivariatePrior { virtual TPriorPtrDoublePr bivariate(const TSize10Vec& marginalize, const TSizeDoublePr10Vec& condition) const { if (N == 2) { - return TPriorPtrDoublePr(std::shared_ptr(this->clone()), 0.0); + return {TPriorPtr(this->clone()), 0.0}; } if (!this->check(marginalize, condition)) { - return TPriorPtrDoublePr(); + return {}; } TSize10Vec i1; this->remainingVariables(marginalize, condition, i1); if (i1.size() != 2) { - return TPriorPtrDoublePr(); + return {}; } maths_t::EDataType dataType = this->dataType(); @@ -472,8 +473,8 @@ class CMultivariateNormalConjugate : public CMultivariatePrior { } } if (condition.empty()) { - return {TPriorPtr(new CMultivariateNormalConjugate<2>( - dataType, m1, p, f, c11, decayRate)), + return {boost::make_unique>( + dataType, m1, p, f, c11, decayRate), 0.0}; } @@ -505,14 +506,14 @@ class CMultivariateNormalConjugate : public CMultivariatePrior { weight -= 0.5 * (xc - m2).transpose() * c22SolvexcMinusm2; LOG_TRACE(<< "mean = " << mean << ", covariance = " << covariance); - return {TPriorPtr(new CMultivariateNormalConjugate<2>( - dataType, mean, p, f, covariance, decayRate)), + return {boost::make_unique>( + dataType, mean, p, f, covariance, decayRate), weight}; } catch (const std::exception& e) { LOG_ERROR(<< "Failed to get univariate prior: " << e.what()); } - return TPriorPtrDoublePr(); + return {}; } //! Get the support for the marginal likelihood function. diff --git a/include/maths/CMultivariateNormalConjugateFactory.h b/include/maths/CMultivariateNormalConjugateFactory.h index fcae08d5cc..fef5886833 100644 --- a/include/maths/CMultivariateNormalConjugateFactory.h +++ b/include/maths/CMultivariateNormalConjugateFactory.h @@ -25,7 +25,7 @@ struct SDistributionRestoreParams; //! \brief Factory for multivariate normal conjugate priors. class MATHS_EXPORT CMultivariateNormalConjugateFactory { public: - using TPriorPtr = std::shared_ptr; + using TPriorPtr = std::unique_ptr; public: //! Create a new non-informative multivariate normal prior. diff --git a/include/maths/CMultivariateOneOfNPriorFactory.h b/include/maths/CMultivariateOneOfNPriorFactory.h index eeeff3eb2c..9c8cf3f1ef 100644 --- a/include/maths/CMultivariateOneOfNPriorFactory.h +++ b/include/maths/CMultivariateOneOfNPriorFactory.h @@ -25,7 +25,7 @@ struct SDistributionRestoreParams; //! \brief Factory for multivariate 1-of-n priors. class MATHS_EXPORT CMultivariateOneOfNPriorFactory { public: - using TPriorPtr = std::shared_ptr; + using TPriorPtr = std::unique_ptr; using TPriorPtrVec = std::vector; public: diff --git a/include/maths/CMultivariatePrior.h b/include/maths/CMultivariatePrior.h index 96c51fc04e..e1dd62009b 100644 --- a/include/maths/CMultivariatePrior.h +++ b/include/maths/CMultivariatePrior.h @@ -46,9 +46,9 @@ class MATHS_EXPORT CMultivariatePrior { using TTail10Vec = core::CSmallVector; using TDouble10VecWeightsAry = maths_t::TDouble10VecWeightsAry; using TDouble10VecWeightsAry1Vec = maths_t::TDouble10VecWeightsAry1Vec; - using TUnivariatePriorPtr = std::shared_ptr; + using TUnivariatePriorPtr = std::unique_ptr; using TUnivariatePriorPtrDoublePr = std::pair; - using TPriorPtr = std::shared_ptr; + using TPriorPtr = std::unique_ptr; using TPriorPtrDoublePr = std::pair; using TWeights = maths_t::CUnitWeights; diff --git a/include/maths/CNaiveBayes.h b/include/maths/CNaiveBayes.h index 5fda126d09..0989e17cfb 100644 --- a/include/maths/CNaiveBayes.h +++ b/include/maths/CNaiveBayes.h @@ -129,7 +129,7 @@ class MATHS_EXPORT CNaiveBayesFeatureDensityFromPrior final : public CNaiveBayes virtual std::string print() const; private: - using TPriorPtr = std::shared_ptr; + using TPriorPtr = std::unique_ptr; private: //! The density model. @@ -149,12 +149,17 @@ class MATHS_EXPORT CNaiveBayes { explicit CNaiveBayes(const CNaiveBayesFeatureDensity& exemplar, double decayRate = 0.0, TOptionalDouble minMaxLogLikelihoodToUseFeature = TOptionalDouble()); - CNaiveBayes(const SDistributionRestoreParams& params, + CNaiveBayes(const CNaiveBayesFeatureDensity& exemplar, + const SDistributionRestoreParams& params, core::CStateRestoreTraverser& traverser); + CNaiveBayes(const CNaiveBayes& other); //! Persist state by passing information to \p inserter. void acceptPersistInserter(core::CStatePersistInserter& inserter) const; + //! Copy by assign operator. + CNaiveBayes& operator=(const CNaiveBayes& other); + //! Efficiently swap the contents of this and \p other. void swap(CNaiveBayes& other); @@ -222,33 +227,47 @@ class MATHS_EXPORT CNaiveBayes { std::string print() const; private: - using TFeatureDensityPtr = std::shared_ptr; + using TFeatureDensityPtr = std::unique_ptr; using TFeatureDensityPtrVec = std::vector; //! \brief The data associated with a class. - struct SClass { - SClass() = default; - SClass(double count, const TFeatureDensityPtrVec& conditionalDensities); + class CClass { + public: + CClass() = default; + explicit CClass(double count); + CClass(const CClass& other); //! Initialize by reading state from \p traverser. bool acceptRestoreTraverser(const SDistributionRestoreParams& params, core::CStateRestoreTraverser& traverser); //! Persist state by passing information to \p inserter. void acceptPersistInserter(core::CStatePersistInserter& inserter) const; + + //! Get the number of examples in this class. + double count() const; + //! Get a writable reference of the number of examples in this class. + double& count(); + //! Get the class conditional densities. + const TFeatureDensityPtrVec& conditionalDensities() const; + //! Get a writable reference of the class conditional densities. + TFeatureDensityPtrVec& conditionalDensities(); + //! Debug the memory used by this object. void debugMemoryUsage(core::CMemoryUsage::TMemoryUsagePtr mem) const; //! Get the memory used by this object. std::size_t memoryUsage() const; + //! Get a checksum for this object. uint64_t checksum(uint64_t seed = 0) const; + private: //! The number of examples in this class. - double s_Count = 0.0; + double m_Count = 0.0; //! The feature conditional densities for this class. - TFeatureDensityPtrVec s_ConditionalDensities; + TFeatureDensityPtrVec m_ConditionalDensities; }; - using TSizeClassUMap = boost::unordered_map; + using TSizeClassUMap = boost::unordered_map; private: //! Initialize by reading state from \p traverser. diff --git a/include/maths/COneOfNPrior.h b/include/maths/COneOfNPrior.h index f04e54ebe0..6df0d101d8 100644 --- a/include/maths/COneOfNPrior.h +++ b/include/maths/COneOfNPrior.h @@ -46,7 +46,7 @@ struct SDistributionRestoreParams; //! value semantics and manage the heap. class MATHS_EXPORT COneOfNPrior : public CPrior { public: - using TPriorPtr = std::shared_ptr; + using TPriorPtr = std::unique_ptr; using TPriorPtrVec = std::vector; using TPriorCPtrVec = std::vector; using TDoublePriorPtrPr = std::pair; diff --git a/include/maths/COrderings.h b/include/maths/COrderings.h index eae1edccb9..99e7df26ee 100644 --- a/include/maths/COrderings.h +++ b/include/maths/COrderings.h @@ -331,6 +331,11 @@ class COrderings : private core::CNonInstantiatable { return SPtrLess::less(lhs.get(), rhs.get()); } + template + bool operator()(const std::unique_ptr& lhs, const std::unique_ptr& rhs) { + return SPtrLess::less(lhs.get(), rhs.get()); + } + template bool operator()(const std::pair& lhs, const std::pair& rhs) const { return lexicographical_compare(lhs.first, lhs.second, rhs.first, @@ -372,6 +377,11 @@ class COrderings : private core::CNonInstantiatable { return SPtrGreater::greater(lhs.get(), rhs.get()); } + template + bool operator()(const std::unique_ptr& lhs, const std::unique_ptr& rhs) { + return SPtrLess::less(lhs.get(), rhs.get()); + } + template bool operator()(const std::pair& lhs, const std::pair& rhs) const { return lexicographical_compare(lhs.first, lhs.second, rhs.first, diff --git a/include/maths/CPriorStateSerialiser.h b/include/maths/CPriorStateSerialiser.h index ddf0977cf0..1b532bc688 100644 --- a/include/maths/CPriorStateSerialiser.h +++ b/include/maths/CPriorStateSerialiser.h @@ -38,14 +38,21 @@ struct SDistributionRestoreParams; //! compatibility in the future as the classes evolve. class MATHS_EXPORT CPriorStateSerialiser { public: - using TPriorPtr = std::shared_ptr; - using TMultivariatePriorPtr = std::shared_ptr; + using TPriorUPtr = std::unique_ptr; + using TPriorSPtr = std::shared_ptr; + using TMultivariatePriorPtr = std::unique_ptr; public: //! Construct the appropriate CPrior sub-class from its state //! document representation. Sets \p ptr to NULL on failure. bool operator()(const SDistributionRestoreParams& params, - TPriorPtr& ptr, + TPriorUPtr& ptr, + core::CStateRestoreTraverser& traverser) const; + + //! Construct the appropriate CPrior sub-class from its state + //! document representation. Sets \p ptr to NULL on failure. + bool operator()(const SDistributionRestoreParams& params, + TPriorSPtr& ptr, core::CStateRestoreTraverser& traverser) const; //! Persist state by passing information to the supplied inserter diff --git a/include/maths/CSeasonalComponentAdaptiveBucketing.h b/include/maths/CSeasonalComponentAdaptiveBucketing.h index cfc4ddaf84..1d4a23aaa4 100644 --- a/include/maths/CSeasonalComponentAdaptiveBucketing.h +++ b/include/maths/CSeasonalComponentAdaptiveBucketing.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -26,7 +27,6 @@ class CStatePersistInserter; class CStateRestoreTraverser; } namespace maths { -class CSeasonalTime; //! \brief An adaptive bucketing of the value of a periodic function. //! @@ -181,7 +181,7 @@ class MATHS_EXPORT CSeasonalComponentAdaptiveBucketing : private CAdaptiveBucket //@} private: - using TSeasonalTimePtr = std::shared_ptr; + using TSeasonalTimePtr = std::unique_ptr; //! \brief The state maintained for each bucket. struct SBucket { diff --git a/include/maths/CSeasonalTime.h b/include/maths/CSeasonalTime.h index 3cdd22d208..2a6212e08e 100644 --- a/include/maths/CSeasonalTime.h +++ b/include/maths/CSeasonalTime.h @@ -246,7 +246,7 @@ class MATHS_EXPORT CSeasonalTimeStateSerializer { public: //! Shared pointer to the CTimeSeriesDecompositionInterface abstract //! base class. - using TSeasonalTimePtr = std::shared_ptr; + using TSeasonalTimePtr = std::unique_ptr; public: //! Construct the appropriate CSeasonalTime sub-class from its state diff --git a/include/maths/CTimeSeriesDecompositionDetail.h b/include/maths/CTimeSeriesDecompositionDetail.h index 34aac7e1c6..81a7bdb50b 100644 --- a/include/maths/CTimeSeriesDecompositionDetail.h +++ b/include/maths/CTimeSeriesDecompositionDetail.h @@ -12,8 +12,10 @@ #include #include +#include #include #include +#include #include #include #include @@ -50,7 +52,7 @@ class MATHS_EXPORT CTimeSeriesDecompositionDetail { }; //! \brief The message passed to add a point. - struct MATHS_EXPORT SAddValue : public SMessage, private core::CNonCopyable { + struct MATHS_EXPORT SAddValue : public SMessage { SAddValue(core_t::TTime time, core_t::TTime lastTime, double value, @@ -60,6 +62,8 @@ class MATHS_EXPORT CTimeSeriesDecompositionDetail { double calendar, const TPredictor& predictor, const CPeriodicityHypothesisTestsConfig& periodicityTestConfig); + SAddValue(const SAddValue&) = delete; + SAddValue& operator=(const SAddValue&) = delete; //! The value to add. double s_Value; @@ -120,10 +124,12 @@ class MATHS_EXPORT CTimeSeriesDecompositionDetail { //! \brief The basic interface for one aspect of the modeling of a time //! series decomposition. - class MATHS_EXPORT CHandler : core::CNonCopyable { + class MATHS_EXPORT CHandler { public: CHandler(); - virtual ~CHandler(); + virtual ~CHandler() = default; + CHandler(const CHandler&) = delete; + CHandler& operator=(const CHandler&) = delete; //! Add a value. virtual void handle(const SAddValue& message); @@ -149,8 +155,12 @@ class MATHS_EXPORT CTimeSeriesDecompositionDetail { }; //! \brief Manages communication between handlers. - class MATHS_EXPORT CMediator : core::CNonCopyable { + class MATHS_EXPORT CMediator { public: + CMediator() = default; + CMediator(const CMediator&) = delete; + CMediator& operator=(const CMediator&) = delete; + //! Forward \p message to all registered models. template void forward(const M& message) const; @@ -183,6 +193,7 @@ class MATHS_EXPORT CTimeSeriesDecompositionDetail { public: CPeriodicityTest(double decayRate, core_t::TTime bucketLength); CPeriodicityTest(const CPeriodicityTest& other, bool isForForecast = false); + CPeriodicityTest& operator=(const CPeriodicityTest&) = delete; //! Initialize by reading state from \p traverser. bool acceptRestoreTraverser(core::CStateRestoreTraverser& traverser); @@ -228,7 +239,7 @@ class MATHS_EXPORT CTimeSeriesDecompositionDetail { private: using TTimeAry = boost::array; - using TExpandingWindowPtr = std::shared_ptr; + using TExpandingWindowPtr = std::unique_ptr; using TExpandingWindowPtrAry = boost::array; private: @@ -272,6 +283,7 @@ class MATHS_EXPORT CTimeSeriesDecompositionDetail { public: CCalendarTest(double decayRate, core_t::TTime bucketLength); CCalendarTest(const CCalendarTest& other, bool isForForecast = false); + CCalendarTest& operator=(const CCalendarTest&) = delete; //! Initialize by reading state from \p traverser. bool acceptRestoreTraverser(core::CStateRestoreTraverser& traverser); @@ -305,7 +317,7 @@ class MATHS_EXPORT CTimeSeriesDecompositionDetail { std::size_t memoryUsage() const; private: - using TCalendarCyclicTestPtr = std::shared_ptr; + using TCalendarCyclicTestPtr = std::unique_ptr; private: //! Handle \p symbol. @@ -342,10 +354,12 @@ class MATHS_EXPORT CTimeSeriesDecompositionDetail { CComponents(const CComponents& other); //! \brief Watches to see if the seasonal components state changes. - class MATHS_EXPORT CScopeNotifyOnStateChange : core::CNonCopyable { + class MATHS_EXPORT CScopeNotifyOnStateChange { public: CScopeNotifyOnStateChange(CComponents& components); ~CScopeNotifyOnStateChange(); + CScopeNotifyOnStateChange(const CScopeNotifyOnStateChange&) = delete; + CScopeNotifyOnStateChange& operator=(const CScopeNotifyOnStateChange&) = delete; //! Check if the seasonal component's state changed. bool changed() const; @@ -663,7 +677,7 @@ class MATHS_EXPORT CTimeSeriesDecompositionDetail { TComponentErrorsVec m_PredictionErrors; }; - using TSeasonalPtr = std::shared_ptr; + using TSeasonalPtr = std::unique_ptr; //! \brief Calendar periodic components of the decomposition. class MATHS_EXPORT CCalendar { @@ -738,7 +752,7 @@ class MATHS_EXPORT CTimeSeriesDecompositionDetail { TComponentErrorsVec m_PredictionErrors; }; - using TCalendarPtr = std::shared_ptr; + using TCalendarPtr = std::unique_ptr; private: //! Get the total size of the components. diff --git a/include/maths/CTimeSeriesDecompositionStateSerialiser.h b/include/maths/CTimeSeriesDecompositionStateSerialiser.h index 732f09474a..380345aa30 100644 --- a/include/maths/CTimeSeriesDecompositionStateSerialiser.h +++ b/include/maths/CTimeSeriesDecompositionStateSerialiser.h @@ -39,16 +39,22 @@ struct STimeSeriesDecompositionRestoreParams; //! compatibility in the future as the classes evolve. class MATHS_EXPORT CTimeSeriesDecompositionStateSerialiser { public: - //! Shared pointer to the CTimeSeriesDecompositionInterface abstract - //! base class. - using TDecompositionPtr = std::shared_ptr; + using TDecompositionUPtr = std::unique_ptr; + using TDecompositionSPtr = std::shared_ptr; public: //! Construct the appropriate CTimeSeriesDecompositionInterface //! sub-class from its state document representation. Sets \p result //! to NULL on failure. bool operator()(const STimeSeriesDecompositionRestoreParams& params, - TDecompositionPtr& result, + TDecompositionUPtr& result, + core::CStateRestoreTraverser& traverser) const; + + //! Construct the appropriate CTimeSeriesDecompositionInterface + //! sub-class from its state document representation. Sets \p result + //! to NULL on failure. + bool operator()(const STimeSeriesDecompositionRestoreParams& params, + TDecompositionSPtr& result, core::CStateRestoreTraverser& traverser) const; //! Persist state by passing information to the supplied inserter. diff --git a/include/maths/CTimeSeriesModel.h b/include/maths/CTimeSeriesModel.h index 8574c1df5e..72e5a34b88 100644 --- a/include/maths/CTimeSeriesModel.h +++ b/include/maths/CTimeSeriesModel.h @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -21,7 +22,6 @@ namespace ml { namespace maths { class CDecayRateController; -class CMultivariatePrior; class CPrior; class CTimeSeriesDecompositionInterface; class CTimeSeriesAnomalyModel; @@ -74,6 +74,8 @@ class MATHS_EXPORT CUnivariateTimeSeriesModel : public CModel { core::CStateRestoreTraverser& traverser); ~CUnivariateTimeSeriesModel(); + const CUnivariateTimeSeriesModel& operator=(const CUnivariateTimeSeriesModel&) = delete; + //! Get the model identifier. virtual std::size_t identifier() const; @@ -211,14 +213,14 @@ class MATHS_EXPORT CUnivariateTimeSeriesModel : public CModel { using TDouble2VecWeightsAryVec = std::vector; using TVector = CVectorNx1; using TVectorMeanAccumulator = CBasicStatistics::SSampleMean::TAccumulator; - using TDecayRateController2AryPtr = std::shared_ptr; + using TDecayRateController2AryPtr = std::unique_ptr; using TPriorPtr = std::shared_ptr; - using TAnomalyModelPtr = std::shared_ptr; + using TAnomalyModelPtr = std::unique_ptr; using TMultivariatePriorCPtrSizePr = std::pair; using TMultivariatePriorCPtrSizePr1Vec = core::CSmallVector; using TModelCPtr1Vec = core::CSmallVector; - using TChangeDetectorPtr = std::shared_ptr; + using TChangeDetectorPtr = std::unique_ptr; private: CUnivariateTimeSeriesModel(const CUnivariateTimeSeriesModel& other, @@ -269,9 +271,13 @@ class MATHS_EXPORT CUnivariateTimeSeriesModel : public CModel { TDecayRateController2AryPtr m_Controllers; //! The time series trend decomposition. + //! + //! \note This can be temporarily be shared with the change detector. TDecompositionPtr m_TrendModel; //! The time series' residual model. + //! + //! \note This can be temporarily be shared with the change detector. TPriorPtr m_ResidualModel; //! A model for time periods when the basic model can't predict the @@ -299,7 +305,7 @@ class MATHS_EXPORT CUnivariateTimeSeriesModel : public CModel { //! \brief Manages the creation correlate models. class MATHS_EXPORT CTimeSeriesCorrelateModelAllocator { public: - using TMultivariatePriorPtr = std::shared_ptr; + using TMultivariatePriorPtr = std::unique_ptr; public: virtual ~CTimeSeriesCorrelateModelAllocator() = default; @@ -346,7 +352,7 @@ class MATHS_EXPORT CTimeSeriesCorrelations { using TSize2Vec = core::CSmallVector; using TSize2Vec1Vec = core::CSmallVector; using TSizeSizePr = std::pair; - using TMultivariatePriorPtr = std::shared_ptr; + using TMultivariatePriorPtr = std::unique_ptr; using TMultivariatePriorPtrDoublePr = std::pair; using TSizeSizePrMultivariatePriorPtrDoublePrUMap = boost::unordered_map; @@ -421,6 +427,8 @@ class MATHS_EXPORT CTimeSeriesCorrelations { using TModelCPtr1Vec = core::CSmallVector; using TSizeSizePrMultivariatePriorPtrDoublePrPr = std::pair; + using TConstSizeSizePrMultivariatePriorPtrDoublePrPr = + std::pair; private: CTimeSeriesCorrelations(const CTimeSeriesCorrelations& other, @@ -441,7 +449,7 @@ class MATHS_EXPORT CTimeSeriesCorrelations { core::CStateRestoreTraverser& traverser); //! Persist the \p model passing information to \p inserter. - static void persist(const TSizeSizePrMultivariatePriorPtrDoublePrPr& model, + static void persist(const TConstSizeSizePrMultivariatePriorPtrDoublePrPr& model, core::CStatePersistInserter& inserter); //! Add the time series identified by \p id. @@ -523,6 +531,9 @@ class MATHS_EXPORT CMultivariateTimeSeriesModel : public CModel { CMultivariateTimeSeriesModel(const CMultivariateTimeSeriesModel& other); CMultivariateTimeSeriesModel(const SModelRestoreParams& params, core::CStateRestoreTraverser& traverser); + ~CMultivariateTimeSeriesModel(); + + const CMultivariateTimeSeriesModel& operator=(const CMultivariateTimeSeriesModel&) = delete; //! Returns 0 since these models don't need a unique identifier. virtual std::size_t identifier() const; @@ -657,9 +668,9 @@ class MATHS_EXPORT CMultivariateTimeSeriesModel : public CModel { using TDouble2VecWeightsAryVec = std::vector; using TVector = CVectorNx1; using TVectorMeanAccumulator = CBasicStatistics::SSampleMean::TAccumulator; - using TDecayRateController2AryPtr = std::shared_ptr; - using TMultivariatePriorPtr = std::shared_ptr; - using TAnomalyModelPtr = std::shared_ptr; + using TDecayRateController2AryPtr = std::unique_ptr; + using TMultivariatePriorPtr = std::unique_ptr; + using TAnomalyModelPtr = std::unique_ptr; private: //! Update the trend with \p samples. diff --git a/include/model/CAnomalyDetector.h b/include/model/CAnomalyDetector.h index 71c40ce92a..e1b6639f50 100644 --- a/include/model/CAnomalyDetector.h +++ b/include/model/CAnomalyDetector.h @@ -73,7 +73,7 @@ class MODEL_EXPORT CAnomalyDetector : private core::CNonCopyable { using TDataGathererPtr = std::shared_ptr; using TModelFactoryCPtr = std::shared_ptr; - using TModelPtr = std::shared_ptr; + using TModelPtr = std::unique_ptr; //! A shared pointer to an instance of this class using TAnomalyDetectorPtr = std::shared_ptr; diff --git a/include/model/CAnomalyDetectorModel.h b/include/model/CAnomalyDetectorModel.h index 695f277f26..d9046f8aec 100644 --- a/include/model/CAnomalyDetectorModel.h +++ b/include/model/CAnomalyDetectorModel.h @@ -8,7 +8,6 @@ #define INCLUDED_ml_model_CAnomalyDetectorModel_h #include -#include #include #include #include @@ -121,7 +120,7 @@ struct SAttributeProbability; //! //! The hierarchy is non-copyable because we don't currently need to be //! able to copy models and the "correct" copy semantics are not obvious. -class MODEL_EXPORT CAnomalyDetectorModel : private core::CNonCopyable { +class MODEL_EXPORT CAnomalyDetectorModel { friend class CModelDetailsView; public: @@ -152,16 +151,20 @@ class MODEL_EXPORT CAnomalyDetectorModel : private core::CNonCopyable { using TFeatureInfluenceCalculatorCPtrPrVec = std::vector; using TFeatureInfluenceCalculatorCPtrPrVecVec = std::vector; - using TMultivariatePriorPtr = std::shared_ptr; - using TFeatureMultivariatePriorPtrPr = std::pair; - using TFeatureMultivariatePriorPtrPrVec = std::vector; - using TMathsModelPtr = std::shared_ptr; - using TMathsModelPtrVec = std::vector; + using TMathsModelSPtr = std::shared_ptr; + using TFeatureMathsModelSPtrPr = std::pair; + using TFeatureMathsModelSPtrPrVec = std::vector; + using TMathsModelUPtr = std::unique_ptr; + using TMathsModelUPtrVec = std::vector; + using TMultivariatePriorSPtr = std::shared_ptr; + using TFeatureMultivariatePriorSPtrPr = std::pair; + using TFeatureMultivariatePriorSPtrPrVec = std::vector; + using TCorrelationsPtr = std::unique_ptr; + using TFeatureCorrelationsPtrPr = std::pair; + using TFeatureCorrelationsPtrPrVec = std::vector; using TDataGathererPtr = std::shared_ptr; - using TModelPtr = std::shared_ptr; - using TModelCPtr = std::shared_ptr; - using TCorrelationsPtr = std::shared_ptr; using CModelDetailsViewPtr = std::auto_ptr; + using TModelPtr = std::unique_ptr; public: //! A value used to indicate a time variable is unset @@ -186,6 +189,7 @@ class MODEL_EXPORT CAnomalyDetectorModel : private core::CNonCopyable { CAnomalyDetectorModel(bool isForPersistence, const CAnomalyDetectorModel& other); virtual ~CAnomalyDetectorModel() = default; + CAnomalyDetectorModel& operator=(const CAnomalyDetectorModel&) = delete; //@} //! Get a human understandable description of the model for debugging. @@ -497,7 +501,11 @@ class MODEL_EXPORT CAnomalyDetectorModel : private core::CNonCopyable { //! \brief The feature models. struct MODEL_EXPORT SFeatureModels { - SFeatureModels(model_t::EFeature feature, TMathsModelPtr newModel); + SFeatureModels(model_t::EFeature feature, TMathsModelSPtr newModel); + SFeatureModels(const SFeatureModels&) = delete; + SFeatureModels& operator=(const SFeatureModels&) = delete; + SFeatureModels(SFeatureModels&& other); + SFeatureModels& operator=(SFeatureModels&& other); //! Restore the models reading state from \p traverser. bool acceptRestoreTraverser(const SModelParams& params, @@ -513,17 +521,21 @@ class MODEL_EXPORT CAnomalyDetectorModel : private core::CNonCopyable { //! The feature. model_t::EFeature s_Feature; //! A prototype model. - TMathsModelPtr s_NewModel; + TMathsModelSPtr s_NewModel; //! The person models. - TMathsModelPtrVec s_Models; + TMathsModelUPtrVec s_Models; }; using TFeatureModelsVec = std::vector; //! \brief The feature correlate models. struct MODEL_EXPORT SFeatureCorrelateModels { SFeatureCorrelateModels(model_t::EFeature feature, - TMultivariatePriorPtr modelPrior, - TCorrelationsPtr model); + const TMultivariatePriorSPtr& modelPrior, + TCorrelationsPtr&& model); + SFeatureCorrelateModels(const SFeatureCorrelateModels&) = delete; + SFeatureCorrelateModels& operator=(const SFeatureCorrelateModels&) = delete; + SFeatureCorrelateModels(SFeatureCorrelateModels&& other); + SFeatureCorrelateModels& operator=(SFeatureCorrelateModels&& other); //! Restore the models reading state from \p traverser. bool acceptRestoreTraverser(const SModelParams& params, @@ -539,7 +551,7 @@ class MODEL_EXPORT CAnomalyDetectorModel : private core::CNonCopyable { //! The feature. model_t::EFeature s_Feature; //! The prototype prior for a correlate model. - TMultivariatePriorPtr s_ModelPrior; + TMultivariatePriorSPtr s_ModelPrior; //! The correlate models. TCorrelationsPtr s_Models; }; @@ -549,6 +561,7 @@ class MODEL_EXPORT CAnomalyDetectorModel : private core::CNonCopyable { class CTimeSeriesCorrelateModelAllocator : public maths::CTimeSeriesCorrelateModelAllocator { public: using TMemoryUsage = std::function; + using TMultivariatePriorUPtr = TMultivariatePriorPtr; public: CTimeSeriesCorrelateModelAllocator(CResourceMonitor& resourceMonitor, @@ -569,10 +582,10 @@ class MODEL_EXPORT CAnomalyDetectorModel : private core::CNonCopyable { virtual std::size_t chunkSize() const; //! Create a new prior for a correlation model. - virtual TMultivariatePriorPtr newPrior() const; + virtual TMultivariatePriorUPtr newPrior() const; //! Set the prototype prior. - void prototypePrior(const TMultivariatePriorPtr& prior); + void prototypePrior(const TMultivariatePriorSPtr& prior); private: //! The global resource monitor. @@ -584,7 +597,7 @@ class MODEL_EXPORT CAnomalyDetectorModel : private core::CNonCopyable { //! The maximum permitted number of correlations which can be modeled. std::size_t m_MaxNumberCorrelations; //! The prototype correlate prior. - TMultivariatePriorPtr m_PrototypePrior; + TMultivariatePriorSPtr m_PrototypePrior; }; protected: diff --git a/include/model/CCountingModelFactory.h b/include/model/CCountingModelFactory.h index 56b4a7580c..820459881d 100644 --- a/include/model/CCountingModelFactory.h +++ b/include/model/CCountingModelFactory.h @@ -79,12 +79,12 @@ class MODEL_EXPORT CCountingModelFactory : public CModelFactory { virtual TPriorPtr defaultPrior(model_t::EFeature feature, const SModelParams& params) const; //! Get the default prior for \p feature which is a stub. - virtual TMultivariatePriorPtr + virtual TMultivariatePriorUPtr defaultMultivariatePrior(model_t::EFeature feature, const SModelParams& params) const; //! Get the default prior for pairs of correlated time series //! of \p feature which is a stub. - virtual TMultivariatePriorPtr + virtual TMultivariatePriorUPtr defaultCorrelatePrior(model_t::EFeature feature, const SModelParams& params) const; //@} diff --git a/include/model/CEventRateModel.h b/include/model/CEventRateModel.h index b9eb787ef8..7d80d524d0 100644 --- a/include/model/CEventRateModel.h +++ b/include/model/CEventRateModel.h @@ -97,9 +97,9 @@ class MODEL_EXPORT CEventRateModel : public CIndividualModel { //! buckets. CEventRateModel(const SModelParams& params, const TDataGathererPtr& dataGatherer, - const TFeatureMathsModelPtrPrVec& newFeatureModels, - const TFeatureMultivariatePriorPtrPrVec& newFeatureCorrelateModelPriors, - const TFeatureCorrelationsPtrPrVec& featureCorrelatesModels, + const TFeatureMathsModelSPtrPrVec& newFeatureModels, + const TFeatureMultivariatePriorSPtrPrVec& newFeatureCorrelateModelPriors, + TFeatureCorrelationsPtrPrVec&& featureCorrelatesModels, const maths::CMultinomialConjugate& probabilityPrior, const TFeatureInfluenceCalculatorCPtrPrVecVec& influenceCalculators, const TInterimBucketCorrectorCPtr& interimBucketCorrector); @@ -110,9 +110,9 @@ class MODEL_EXPORT CEventRateModel : public CIndividualModel { //! and so must be sampled for before this model can be used. CEventRateModel(const SModelParams& params, const TDataGathererPtr& dataGatherer, - const TFeatureMathsModelPtrPrVec& newFeatureModels, - const TFeatureMultivariatePriorPtrPrVec& newFeatureCorrelateModelPriors, - const TFeatureCorrelationsPtrPrVec& featureCorrelatesModels, + const TFeatureMathsModelSPtrPrVec& newFeatureModels, + const TFeatureMultivariatePriorSPtrPrVec& newFeatureCorrelateModelPriors, + TFeatureCorrelationsPtrPrVec&& featureCorrelatesModels, const TFeatureInfluenceCalculatorCPtrPrVecVec& influenceCalculators, const TInterimBucketCorrectorCPtr& interimBucketCorrector, core::CStateRestoreTraverser& traverser); diff --git a/include/model/CEventRateModelFactory.h b/include/model/CEventRateModelFactory.h index f1b9dcff9e..34b72e38b0 100644 --- a/include/model/CEventRateModelFactory.h +++ b/include/model/CEventRateModelFactory.h @@ -86,7 +86,7 @@ class MODEL_EXPORT CEventRateModelFactory final : public CModelFactory { //! //! \param[in] feature The feature for which to get the prior. //! \param[in] params The model parameters. - virtual TMultivariatePriorPtr + virtual TMultivariatePriorUPtr defaultMultivariatePrior(model_t::EFeature feature, const SModelParams& params) const; //! Get the default prior for pairs of correlated time series @@ -94,7 +94,7 @@ class MODEL_EXPORT CEventRateModelFactory final : public CModelFactory { //! //! \param[in] feature The feature for which to get the prior. //! \param[in] params The model parameters. - virtual TMultivariatePriorPtr + virtual TMultivariatePriorUPtr defaultCorrelatePrior(model_t::EFeature feature, const SModelParams& params) const; //@} diff --git a/include/model/CEventRatePopulationModel.h b/include/model/CEventRatePopulationModel.h index a8f19fa2f7..3d28b9d326 100644 --- a/include/model/CEventRatePopulationModel.h +++ b/include/model/CEventRatePopulationModel.h @@ -74,12 +74,6 @@ namespace model { //! state can be maintained. class MODEL_EXPORT CEventRatePopulationModel : public CPopulationModel { public: - using TFeatureMathsModelPtrPr = std::pair; - using TFeatureMathsModelPtrPrVec = std::vector; - using TFeatureMathsModelPtrVecPr = std::pair; - using TFeatureMathsModelPtrVecPrVec = std::vector; - using TFeatureCorrelationsPtrPr = std::pair; - using TFeatureCorrelationsPtrPrVec = std::vector; using TSizeSizePrUInt64Pr = std::pair; using TSizeSizePrUInt64PrVec = std::vector; using TFeatureData = SEventRateFeatureData; @@ -133,9 +127,9 @@ class MODEL_EXPORT CEventRatePopulationModel : public CPopulationModel { //! and so must be sampled for before this model can be used. CEventRatePopulationModel(const SModelParams& params, const TDataGathererPtr& dataGatherer, - const TFeatureMathsModelPtrPrVec& newFeatureModels, - const TFeatureMultivariatePriorPtrPrVec& newFeatureCorrelateModelPriors, - const TFeatureCorrelationsPtrPrVec& featureCorrelatesModels, + const TFeatureMathsModelSPtrPrVec& newFeatureModels, + const TFeatureMultivariatePriorSPtrPrVec& newFeatureCorrelateModelPriors, + TFeatureCorrelationsPtrPrVec&& featureCorrelatesModels, const TFeatureInfluenceCalculatorCPtrPrVecVec& influenceCalculators, const TInterimBucketCorrectorCPtr& interimBucketCorrector); @@ -145,9 +139,9 @@ class MODEL_EXPORT CEventRatePopulationModel : public CPopulationModel { //! and so must be sampled for before this model can be used. CEventRatePopulationModel(const SModelParams& params, const TDataGathererPtr& dataGatherer, - const TFeatureMathsModelPtrPrVec& newFeatureModels, - const TFeatureMultivariatePriorPtrPrVec& newFeatureCorrelateModelPriors, - const TFeatureCorrelationsPtrPrVec& featureCorrelatesModels, + const TFeatureMathsModelSPtrPrVec& newFeatureModels, + const TFeatureMultivariatePriorSPtrPrVec& newFeatureCorrelateModelPriors, + TFeatureCorrelationsPtrPrVec&& featureCorrelatesModels, const TFeatureInfluenceCalculatorCPtrPrVecVec& influenceCalculators, const TInterimBucketCorrectorCPtr& interimBucketCorrector, core::CStateRestoreTraverser& traverser); @@ -158,6 +152,8 @@ class MODEL_EXPORT CEventRatePopulationModel : public CPopulationModel { //! redundant except to create a signature that will not be mistaken //! for a general purpose copy constructor. CEventRatePopulationModel(bool isForPersistence, const CEventRatePopulationModel& other); + CEventRatePopulationModel(const CEventRatePopulationModel&) = delete; + CEventRatePopulationModel& operator=(const CEventRatePopulationModel&) = delete; //@} //! \name Persistence @@ -309,9 +305,9 @@ class MODEL_EXPORT CEventRatePopulationModel : public CPopulationModel { private: //! Initialize the feature models. - void initialize(const TFeatureMathsModelPtrPrVec& newFeatureModels, - const TFeatureMultivariatePriorPtrPrVec& newFeatureCorrelateModelPriors, - const TFeatureCorrelationsPtrPrVec& featureCorrelatesModels); + void initialize(const TFeatureMathsModelSPtrPrVec& newFeatureModels, + const TFeatureMultivariatePriorSPtrPrVec& newFeatureCorrelateModelPriors, + TFeatureCorrelationsPtrPrVec&& featureCorrelatesModels); //! Get the start time of the current bucket. virtual core_t::TTime currentBucketStartTime() const; diff --git a/include/model/CEventRatePopulationModelFactory.h b/include/model/CEventRatePopulationModelFactory.h index 887ee60ec2..bec5da8575 100644 --- a/include/model/CEventRatePopulationModelFactory.h +++ b/include/model/CEventRatePopulationModelFactory.h @@ -87,7 +87,7 @@ class MODEL_EXPORT CEventRatePopulationModelFactory final : public CModelFactory //! //! \param[in] feature The feature for which to get the prior. //! \param[in] params The model parameters. - virtual TMultivariatePriorPtr + virtual TMultivariatePriorUPtr defaultMultivariatePrior(model_t::EFeature feature, const SModelParams& params) const; //! Get the default prior for pairs of correlated time series @@ -95,7 +95,7 @@ class MODEL_EXPORT CEventRatePopulationModelFactory final : public CModelFactory //! //! \param[in] feature The feature for which to get the prior. //! \param[in] params The model parameters. - virtual TMultivariatePriorPtr + virtual TMultivariatePriorUPtr defaultCorrelatePrior(model_t::EFeature feature, const SModelParams& params) const; //@} diff --git a/include/model/CForecastModelPersist.h b/include/model/CForecastModelPersist.h index 079f42ad6e..49450c09ef 100644 --- a/include/model/CForecastModelPersist.h +++ b/include/model/CForecastModelPersist.h @@ -39,7 +39,7 @@ namespace model { //! locally never leaving process/io boundaries. class MODEL_EXPORT CForecastModelPersist final { public: - using TMathsModelPtr = std::shared_ptr; + using TMathsModelPtr = std::unique_ptr; public: class MODEL_EXPORT CPersist final { diff --git a/include/model/CIndividualModel.h b/include/model/CIndividualModel.h index 0d3f380bc0..b2ed9e62fc 100644 --- a/include/model/CIndividualModel.h +++ b/include/model/CIndividualModel.h @@ -53,12 +53,6 @@ class MODEL_EXPORT CIndividualModel : public CAnomalyDetectorModel { using TFeatureSizeSizeTriple = core::CTriple; using TFeatureSizeSizeTripleDouble1VecUMap = boost::unordered_map; - using TFeatureMathsModelPtrPr = std::pair; - using TFeatureMathsModelPtrPrVec = std::vector; - using TFeatureMathsModelPtrVecPr = std::pair; - using TFeatureMathsModelPtrVecPrVec = std::vector; - using TFeatureCorrelationsPtrPr = std::pair; - using TFeatureCorrelationsPtrPrVec = std::vector; public: //! \name Life-cycle @@ -76,9 +70,9 @@ class MODEL_EXPORT CIndividualModel : public CAnomalyDetectorModel { //! and so must be sampled for before this model can be used. CIndividualModel(const SModelParams& params, const TDataGathererPtr& dataGatherer, - const TFeatureMathsModelPtrPrVec& newFeatureModels, - const TFeatureMultivariatePriorPtrPrVec& newFeatureCorrelateModelPriors, - const TFeatureCorrelationsPtrPrVec& featureCorrelatesModels, + const TFeatureMathsModelSPtrPrVec& newFeatureModels, + const TFeatureMultivariatePriorSPtrPrVec& newFeatureCorrelateModelPriors, + TFeatureCorrelationsPtrPrVec&& featureCorrelatesModels, const TFeatureInfluenceCalculatorCPtrPrVecVec& influenceCalculators); //! Create a copy that will result in the same persisted state as the @@ -87,6 +81,8 @@ class MODEL_EXPORT CIndividualModel : public CAnomalyDetectorModel { //! redundant except to create a signature that will not be mistaken //! for a general purpose copy constructor. CIndividualModel(bool isForPersistence, const CIndividualModel& other); + CIndividualModel(const CIndividualModel&) = delete; + CIndividualModel& operator=(const CIndividualModel&) = delete; //@} //! Returns false. diff --git a/include/model/CMetricModel.h b/include/model/CMetricModel.h index 7946249bd2..a7eca11e4e 100644 --- a/include/model/CMetricModel.h +++ b/include/model/CMetricModel.h @@ -91,9 +91,9 @@ class MODEL_EXPORT CMetricModel : public CIndividualModel { //! buckets. CMetricModel(const SModelParams& params, const TDataGathererPtr& dataGatherer, - const TFeatureMathsModelPtrPrVec& newFeatureModels, - const TFeatureMultivariatePriorPtrPrVec& newFeatureCorrelateModelPriors, - const TFeatureCorrelationsPtrPrVec& featureCorrelatesModels, + const TFeatureMathsModelSPtrPrVec& newFeatureModels, + const TFeatureMultivariatePriorSPtrPrVec& newFeatureCorrelateModelPriors, + TFeatureCorrelationsPtrPrVec&& featureCorrelatesModels, const TFeatureInfluenceCalculatorCPtrPrVecVec& influenceCalculators, const TInterimBucketCorrectorCPtr& interimBucketCorrector); @@ -103,9 +103,9 @@ class MODEL_EXPORT CMetricModel : public CIndividualModel { //! and so must be sampled for before this model can be used. CMetricModel(const SModelParams& params, const TDataGathererPtr& dataGatherer, - const TFeatureMathsModelPtrPrVec& newFeatureModels, - const TFeatureMultivariatePriorPtrPrVec& newFeatureCorrelateModelPriors, - const TFeatureCorrelationsPtrPrVec& featureCorrelatesModels, + const TFeatureMathsModelSPtrPrVec& newFeatureModels, + const TFeatureMultivariatePriorSPtrPrVec& newFeatureCorrelateModelPriors, + TFeatureCorrelationsPtrPrVec&& featureCorrelatesModels, const TFeatureInfluenceCalculatorCPtrPrVecVec& influenceCalculators, const TInterimBucketCorrectorCPtr& interimBucketCorrector, core::CStateRestoreTraverser& traverser); diff --git a/include/model/CMetricModelFactory.h b/include/model/CMetricModelFactory.h index 267bcf34d8..8b77d304ed 100644 --- a/include/model/CMetricModelFactory.h +++ b/include/model/CMetricModelFactory.h @@ -86,7 +86,7 @@ class MODEL_EXPORT CMetricModelFactory final : public CModelFactory { //! //! \param[in] feature The feature for which to get the prior. //! \param[in] params The model parameters. - virtual TMultivariatePriorPtr + virtual TMultivariatePriorUPtr defaultMultivariatePrior(model_t::EFeature feature, const SModelParams& params) const; //! Get the default prior for pairs of correlated time series @@ -94,7 +94,7 @@ class MODEL_EXPORT CMetricModelFactory final : public CModelFactory { //! //! \param[in] feature The feature for which to get the prior. //! \param[in] params The model parameters. - virtual TMultivariatePriorPtr + virtual TMultivariatePriorUPtr defaultCorrelatePrior(model_t::EFeature feature, const SModelParams& params) const; //@} diff --git a/include/model/CMetricPopulationModel.h b/include/model/CMetricPopulationModel.h index a851ce1c48..601f3d7622 100644 --- a/include/model/CMetricPopulationModel.h +++ b/include/model/CMetricPopulationModel.h @@ -53,12 +53,6 @@ namespace model { //! state can be maintained. class MODEL_EXPORT CMetricPopulationModel : public CPopulationModel { public: - using TFeatureMathsModelPtrPr = std::pair; - using TFeatureMathsModelPtrPrVec = std::vector; - using TFeatureMathsModelPtrVecPr = std::pair; - using TFeatureMathsModelPtrVecPrVec = std::vector; - using TFeatureCorrelationsPtrPr = std::pair; - using TFeatureCorrelationsPtrPrVec = std::vector; using TFeatureData = SMetricFeatureData; using TSizeSizePrFeatureDataPr = std::pair; using TSizeSizePrFeatureDataPrVec = std::vector; @@ -109,9 +103,9 @@ class MODEL_EXPORT CMetricPopulationModel : public CPopulationModel { //! and so must be sampled for before this model can be used. CMetricPopulationModel(const SModelParams& params, const TDataGathererPtr& dataGatherer, - const TFeatureMathsModelPtrPrVec& newFeatureModels, - const TFeatureMultivariatePriorPtrPrVec& newFeatureCorrelateModelPriors, - const TFeatureCorrelationsPtrPrVec& featureCorrelatesModels, + const TFeatureMathsModelSPtrPrVec& newFeatureModels, + const TFeatureMultivariatePriorSPtrPrVec& newFeatureCorrelateModelPriors, + TFeatureCorrelationsPtrPrVec&& featureCorrelatesModels, const TFeatureInfluenceCalculatorCPtrPrVecVec& influenceCalculators, const TInterimBucketCorrectorCPtr& interimBucketCorrector); @@ -121,9 +115,9 @@ class MODEL_EXPORT CMetricPopulationModel : public CPopulationModel { //! and so must be sampled for before this model can be used. CMetricPopulationModel(const SModelParams& params, const TDataGathererPtr& dataGatherer, - const TFeatureMathsModelPtrPrVec& newFeatureModels, - const TFeatureMultivariatePriorPtrPrVec& newFeatureCorrelateModelPriors, - const TFeatureCorrelationsPtrPrVec& featureCorrelatesModels, + const TFeatureMathsModelSPtrPrVec& newFeatureModels, + const TFeatureMultivariatePriorSPtrPrVec& newFeatureCorrelateModelPriors, + TFeatureCorrelationsPtrPrVec&& featureCorrelatesModels, const TFeatureInfluenceCalculatorCPtrPrVecVec& influenceCalculators, const TInterimBucketCorrectorCPtr& interimBucketCorrector, core::CStateRestoreTraverser& traverser); @@ -134,6 +128,8 @@ class MODEL_EXPORT CMetricPopulationModel : public CPopulationModel { //! redundant except to create a signature that will not be mistaken //! for a general purpose copy constructor. CMetricPopulationModel(bool isForPersistence, const CMetricPopulationModel& other); + CMetricPopulationModel(const CMetricPopulationModel&) = delete; + CMetricPopulationModel& operator=(const CMetricPopulationModel&) = delete; //@} //! Returns false. @@ -285,9 +281,9 @@ class MODEL_EXPORT CMetricPopulationModel : public CPopulationModel { private: //! Initialize the feature models. - void initialize(const TFeatureMathsModelPtrPrVec& newFeatureModels, - const TFeatureMultivariatePriorPtrPrVec& newFeatureCorrelateModelPriors, - const TFeatureCorrelationsPtrPrVec& featureCorrelatesModels); + void initialize(const TFeatureMathsModelSPtrPrVec& newFeatureModels, + const TFeatureMultivariatePriorSPtrPrVec& newFeatureCorrelateModelPriors, + TFeatureCorrelationsPtrPrVec&& featureCorrelatesModels); //! Get the start time of the current bucket. virtual core_t::TTime currentBucketStartTime() const; diff --git a/include/model/CMetricPopulationModelFactory.h b/include/model/CMetricPopulationModelFactory.h index cd65ec1795..9ba356514b 100644 --- a/include/model/CMetricPopulationModelFactory.h +++ b/include/model/CMetricPopulationModelFactory.h @@ -87,7 +87,7 @@ class MODEL_EXPORT CMetricPopulationModelFactory final : public CModelFactory { //! //! \param[in] feature The feature for which to get the prior. //! \param[in] params The model parameters. - virtual TMultivariatePriorPtr + virtual TMultivariatePriorUPtr defaultMultivariatePrior(model_t::EFeature feature, const SModelParams& params) const; //! Get the default prior for pairs of correlated time series @@ -95,7 +95,7 @@ class MODEL_EXPORT CMetricPopulationModelFactory final : public CModelFactory { //! //! \param[in] feature The feature for which to get the prior. //! \param[in] params The model parameters. - virtual TMultivariatePriorPtr + virtual TMultivariatePriorUPtr defaultCorrelatePrior(model_t::EFeature feature, const SModelParams& params) const; //@} diff --git a/include/model/CModelFactory.h b/include/model/CModelFactory.h index dfc0884ee4..4e4b9a69b0 100644 --- a/include/model/CModelFactory.h +++ b/include/model/CModelFactory.h @@ -73,17 +73,18 @@ class MODEL_EXPORT CModelFactory { using TStrCRef = boost::reference_wrapper; using TStrCRefVec = std::vector; using TDataGathererPtr = std::shared_ptr; - using TPriorPtr = std::shared_ptr; - using TMultivariatePriorPtr = std::shared_ptr; - using TFeatureMultivariatePriorPtrPr = std::pair; - using TFeatureMultivariatePriorPtrPrVec = std::vector; + using TPriorPtr = std::unique_ptr; + using TMultivariatePriorSPtr = std::shared_ptr; + using TMultivariatePriorUPtr = std::unique_ptr; + using TFeatureMultivariatePriorSPtrPr = std::pair; + using TFeatureMultivariatePriorSPtrPrVec = std::vector; using TDecompositionCPtr = std::shared_ptr; using TMathsModelPtr = std::shared_ptr; - using TCorrelationsPtr = std::shared_ptr; - using TFeatureCorrelationsPtrPr = std::pair; - using TFeatureCorrelationsPtrPrVec = std::vector; using TFeatureMathsModelPtrPr = std::pair; using TFeatureMathsModelPtrPrVec = std::vector; + using TCorrelationsPtr = std::unique_ptr; + using TFeatureCorrelationsPtrPr = std::pair; + using TFeatureCorrelationsPtrPrVec = std::vector; using TModelPtr = std::shared_ptr; using TModelCPtr = std::shared_ptr; using TInfluenceCalculatorCPtr = std::shared_ptr; @@ -198,21 +199,21 @@ class MODEL_EXPORT CModelFactory { //! Get the default correlate priors to use for correlated pairs of time //! series of \p features. - const TFeatureMultivariatePriorPtrPrVec& + const TFeatureMultivariatePriorSPtrPrVec& defaultCorrelatePriors(const TFeatureVec& features) const; //! Get the default models for correlations of \p features. - const TFeatureCorrelationsPtrPrVec& defaultCorrelates(const TFeatureVec& features) const; + TFeatureCorrelationsPtrPrVec defaultCorrelates(const TFeatureVec& features) const; //! Get the default prior to use for \p feature. TPriorPtr defaultPrior(model_t::EFeature feature) const; //! Get the default prior to use for multivariate \p feature. - TMultivariatePriorPtr defaultMultivariatePrior(model_t::EFeature feature) const; + TMultivariatePriorUPtr defaultMultivariatePrior(model_t::EFeature feature) const; //! Get the default prior to use for correlared pairs of time //! series for univariate \p feature. - TMultivariatePriorPtr defaultCorrelatePrior(model_t::EFeature feature) const; + TMultivariatePriorUPtr defaultCorrelatePrior(model_t::EFeature feature) const; //! Get the default prior for \p feature. //! @@ -225,7 +226,7 @@ class MODEL_EXPORT CModelFactory { //! //! \param[in] feature The feature for which to get the prior. //! \param[in] params The model parameters. - virtual TMultivariatePriorPtr + virtual TMultivariatePriorUPtr defaultMultivariatePrior(model_t::EFeature feature, const SModelParams& params) const = 0; //! Get the default prior for pairs of correlated time series @@ -233,7 +234,7 @@ class MODEL_EXPORT CModelFactory { //! //! \param[in] feature The feature for which to get the prior. //! \param[in] params The model parameters. - virtual TMultivariatePriorPtr + virtual TMultivariatePriorUPtr defaultCorrelatePrior(model_t::EFeature feature, const SModelParams& params) const = 0; //! Get the default prior to use for categorical data. @@ -364,7 +365,7 @@ class MODEL_EXPORT CModelFactory { virtual double minimumSeasonalVarianceScale() const = 0; protected: - using TMultivariatePriorPtrVec = std::vector; + using TMultivariatePriorUPtrVec = std::vector; using TOptionalSearchKey = boost::optional; protected: @@ -381,15 +382,15 @@ class MODEL_EXPORT CModelFactory { //! \param[in] dimension The dimension. //! \param[in] params The model parameters. //! \warning Up to ten dimensions are supported. - TMultivariatePriorPtr multivariateNormalPrior(std::size_t dimension, - const SModelParams& params) const; + TMultivariatePriorUPtr multivariateNormalPrior(std::size_t dimension, + const SModelParams& params) const; //! Get a multivariate multimodal prior with dimension \p dimension. //! //! \param[in] dimension The dimension. //! \param[in] params The model parameters. //! \warning Up to ten dimensions are supported. - TMultivariatePriorPtr + TMultivariatePriorUPtr multivariateMultimodalPrior(std::size_t dimension, const SModelParams& params, const maths::CMultivariatePrior& modePrior) const; @@ -399,9 +400,9 @@ class MODEL_EXPORT CModelFactory { //! \param[in] dimension The dimension. //! \param[in] params The model parameters. //! \param[in] models The component models to select between. - TMultivariatePriorPtr multivariateOneOfNPrior(std::size_t dimension, - const SModelParams& params, - const TMultivariatePriorPtrVec& models) const; + TMultivariatePriorUPtr multivariateOneOfNPrior(std::size_t dimension, + const SModelParams& params, + const TMultivariatePriorUPtrVec& models) const; //! Get the default prior for time-of-day and time-of-week modeling. //! This is just a mixture of normals which allows more modes than @@ -415,13 +416,12 @@ class MODEL_EXPORT CModelFactory { //! modes than we typically do. //! //! \param[in] params The model parameters. - TMultivariatePriorPtr latLongPrior(const SModelParams& params) const; + TMultivariatePriorUPtr latLongPrior(const SModelParams& params) const; private: using TFeatureVecMathsModelMap = std::map; using TFeatureVecMultivariatePriorMap = - std::map; - using TFeatureVecCorrelationsMap = std::map; + std::map; using TStrFeatureVecPr = std::pair; using TStrFeatureVecPrInfluenceCalculatorCPtrMap = std::map; @@ -449,9 +449,6 @@ class MODEL_EXPORT CModelFactory { //! A cache of priors for correlate pairs of collections of features. mutable TFeatureVecMultivariatePriorMap m_CorrelatePriorCache; - //! A cache of models of the correlations of collections of features. - mutable TFeatureVecCorrelationsMap m_CorrelationsCache; - //! A cache of influence calculators for collections of features. mutable TStrFeatureVecPrInfluenceCalculatorCPtrMap m_InfluenceCalculatorCache; }; diff --git a/lib/core/unittest/CMemoryUsageTest.cc b/lib/core/unittest/CMemoryUsageTest.cc index da49785758..17f9c9b6f7 100644 --- a/lib/core/unittest/CMemoryUsageTest.cc +++ b/lib/core/unittest/CMemoryUsageTest.cc @@ -508,7 +508,8 @@ void CMemoryUsageTest::testUsage() { LOG_DEBUG(<< "expected dynamic size = " << sizeof(SBar) + sizeof(SFoo) * value.s_State.capacity()); CPPUNIT_ASSERT_EQUAL(core::CMemory::dynamicSize(pointer), - sizeof(SBar) + sizeof(SFoo) * value.s_State.capacity()); + sizeof(long) + sizeof(SBar) + + sizeof(SFoo) * value.s_State.capacity()); } { @@ -625,7 +626,7 @@ void CMemoryUsageTest::testUsage() { core::CMemory::dynamicSize(basederivedPtr)); TBasePtr sPtr(new CDerived(6)); - CPPUNIT_ASSERT_EQUAL(sPtr->memoryUsage() + sizeof(CDerived), + CPPUNIT_ASSERT_EQUAL(sPtr->memoryUsage() + sizeof(long) + sizeof(CDerived), core::CMemory::dynamicSize(sPtr)); } { @@ -657,9 +658,11 @@ void CMemoryUsageTest::testUsage() { std::size_t total = core::CMemory::dynamicSize(vec); std::size_t calc = vec.capacity() * sizeof(TBasePtr); for (std::size_t i = 0; i < 6; ++i) { + calc += sizeof(long); calc += static_cast(vec[i].get())->memoryUsage(); calc += sizeof(CBase); } + calc += sizeof(long); calc += static_cast(vec[6].get())->memoryUsage(); calc += sizeof(CDerived); CPPUNIT_ASSERT_EQUAL(calc, total); @@ -1113,8 +1116,8 @@ void CMemoryUsageTest::testSharedPointer() { // = 688 std::size_t expectedSize = - vec1.capacity() * sizeof(TIntVecPtr) + - vec2.capacity() * sizeof(TIntVecPtr) + 3 * sizeof(TIntVec) + + vec1.capacity() * sizeof(TIntVecPtr) + vec2.capacity() * sizeof(TIntVecPtr) + + 3 * (sizeof(long) + sizeof(TIntVec)) + (vec1[0]->capacity() + vec1[1]->capacity() + vec1[3]->capacity()) * sizeof(int); LOG_DEBUG(<< "Expected: " << expectedSize << ", actual: " diff --git a/lib/maths/CClustererStateSerialiser.cc b/lib/maths/CClustererStateSerialiser.cc index 124d4b2191..5bec0134b0 100644 --- a/lib/maths/CClustererStateSerialiser.cc +++ b/lib/maths/CClustererStateSerialiser.cc @@ -11,6 +11,8 @@ #include #include +#include + namespace ml { namespace maths { @@ -31,10 +33,10 @@ bool CClustererStateSerialiser::operator()(const SDistributionRestoreParams& par do { const std::string& name = traverser.name(); if (name == CClustererTypes::X_MEANS_ONLINE_1D_TAG) { - ptr.reset(new CXMeansOnline1d(params, splitFunc, mergeFunc, traverser)); + ptr = boost::make_unique(params, splitFunc, mergeFunc, traverser); ++numResults; } else if (name == CClustererTypes::K_MEANS_ONLINE_1D_TAG) { - ptr.reset(new CKMeansOnline1d(params, traverser)); + ptr = boost::make_unique(params, traverser); ++numResults; } else { LOG_ERROR(<< "No clusterer corresponds to node name " << traverser.name()); diff --git a/lib/maths/CModelStateSerialiser.cc b/lib/maths/CModelStateSerialiser.cc index adbde792d3..ebe0d14b71 100644 --- a/lib/maths/CModelStateSerialiser.cc +++ b/lib/maths/CModelStateSerialiser.cc @@ -9,6 +9,7 @@ #include #include +#include namespace ml { namespace maths { @@ -26,13 +27,13 @@ bool CModelStateSerialiser::operator()(const SModelRestoreParams& params, do { const std::string& name = traverser.name(); if (name == UNIVARIATE_TIME_SERIES_TAG) { - result.reset(new CUnivariateTimeSeriesModel(params, traverser)); + result = boost::make_unique(params, traverser); ++numResults; } else if (name == MULTIVARIATE_TIME_SERIES_TAG) { - result.reset(new CMultivariateTimeSeriesModel(params, traverser)); + result = boost::make_unique(params, traverser); ++numResults; } else if (name == MODEL_STUB_TAG) { - result.reset(new CModelStub()); + result = boost::make_unique(); ++numResults; } else { LOG_ERROR(<< "No model corresponds to name " << traverser.name()); diff --git a/lib/maths/CMultimodalPrior.cc b/lib/maths/CMultimodalPrior.cc index 3a5cc55c4f..50e507d487 100644 --- a/lib/maths/CMultimodalPrior.cc +++ b/lib/maths/CMultimodalPrior.cc @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -92,7 +93,7 @@ CMultimodalPrior::CMultimodalPrior(maths_t::EDataType dataType, normals.emplace_back(dataType, moments_, decayRate); } - m_Clusterer.reset(new CKMeansOnline1d(normals)); + m_Clusterer = boost::make_unique(normals); m_Modes.reserve(normals.size()); for (std::size_t i = 0u; i < normals.size(); ++i) { @@ -104,7 +105,7 @@ CMultimodalPrior::CMultimodalPrior(maths_t::EDataType dataType, double decayRate : CPrior(dataType, decayRate) { m_Modes.reserve(priors.size()); for (std::size_t i = 0u; i < priors.size(); ++i) { - m_Modes.emplace_back(i, priors[i]); + m_Modes.emplace_back(i, std::move(priors[i])); } } @@ -132,7 +133,7 @@ bool CMultimodalPrior::acceptRestoreTraverser(const SDistributionRestoreParams& MODE_TAG, TMode mode, traverser.traverseSubLevel(boost::bind(&TMode::acceptRestoreTraverser, &mode, boost::cref(params), _1)), - m_Modes.push_back(mode)) + m_Modes.push_back(std::move(mode))) RESTORE_SETUP_TEARDOWN(NUMBER_SAMPLES_TAG, double numberSamples, core::CStringUtils::stringToType(traverser.value(), numberSamples), this->numberSamples(numberSamples)) @@ -637,7 +638,7 @@ void CMultimodalPrior::CModeSplitCallback::operator()(std::size_t sourceIndex, // Create the child modes. LOG_TRACE(<< "Creating mode with index " << leftSplitIndex); - modes.emplace_back(leftSplitIndex, m_Prior->m_SeedPrior); + modes.emplace_back(leftSplitIndex, TPriorPtr(m_Prior->m_SeedPrior->clone())); { TDoubleVec samples; if (!m_Prior->m_Clusterer->sample(leftSplitIndex, MODE_SPLIT_NUMBER_SAMPLES, samples)) { @@ -661,7 +662,7 @@ void CMultimodalPrior::CModeSplitCallback::operator()(std::size_t sourceIndex, } LOG_TRACE(<< "Creating mode with index " << rightSplitIndex); - modes.emplace_back(rightSplitIndex, m_Prior->m_SeedPrior); + modes.emplace_back(rightSplitIndex, TPriorPtr(m_Prior->m_SeedPrior->clone())); { TDoubleVec samples; if (!m_Prior->m_Clusterer->sample(rightSplitIndex, MODE_SPLIT_NUMBER_SAMPLES, samples)) { @@ -707,7 +708,7 @@ void CMultimodalPrior::CModeMergeCallback::operator()(std::size_t leftMergeIndex TModeVec& modes = m_Prior->m_Modes; // Create the new mode. - TMode newMode(targetIndex, m_Prior->m_SeedPrior); + TMode newMode(targetIndex, TPriorPtr(m_Prior->m_SeedPrior->clone())); double wl = 0.0; double wr = 0.0; @@ -778,7 +779,7 @@ void CMultimodalPrior::CModeMergeCallback::operator()(std::size_t leftMergeIndex // Add the new mode. LOG_TRACE(<< "Creating mode with index " << targetIndex); - modes.push_back(newMode); + modes.push_back(std::move(newMode)); m_Prior->checkInvariants("MERGE: "); diff --git a/lib/maths/CMultivariateConstantPrior.cc b/lib/maths/CMultivariateConstantPrior.cc index 73ad2ea920..300c1c57ca 100644 --- a/lib/maths/CMultivariateConstantPrior.cc +++ b/lib/maths/CMultivariateConstantPrior.cc @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -116,7 +117,7 @@ CMultivariateConstantPrior::TUnivariatePriorPtrDoublePr CMultivariateConstantPrior::univariate(const TSize10Vec& marginalize, const TSizeDoublePr10Vec& condition) const { if (!this->check(marginalize, condition)) { - return TUnivariatePriorPtrDoublePr(); + return {}; } TSize10Vec i1; @@ -125,24 +126,24 @@ CMultivariateConstantPrior::univariate(const TSize10Vec& marginalize, LOG_ERROR(<< "Invalid variables for computing univariate distribution: " << "marginalize '" << core::CContainerPrinter::print(marginalize) << "'" << ", condition '" << core::CContainerPrinter::print(condition) << "'"); - return TUnivariatePriorPtrDoublePr(); + return {}; } return this->isNonInformative() - ? TUnivariatePriorPtrDoublePr(TUnivariatePriorPtr(new CConstantPrior), 0.0) + ? TUnivariatePriorPtrDoublePr(boost::make_unique(), 0.0) : TUnivariatePriorPtrDoublePr( - TUnivariatePriorPtr(new CConstantPrior((*m_Constant)[i1[0]])), 0.0); + boost::make_unique((*m_Constant)[i1[0]]), 0.0); } CMultivariateConstantPrior::TPriorPtrDoublePr CMultivariateConstantPrior::bivariate(const TSize10Vec& marginalize, const TSizeDoublePr10Vec& condition) const { if (m_Dimension == 2) { - return TPriorPtrDoublePr(TPriorPtr(this->clone()), 0.0); + return {TPriorPtr(this->clone()), 0.0}; } if (!this->check(marginalize, condition)) { - return TPriorPtrDoublePr(); + return {}; } TSize10Vec i1; @@ -151,16 +152,16 @@ CMultivariateConstantPrior::bivariate(const TSize10Vec& marginalize, LOG_ERROR(<< "Invalid variables for computing univariate distribution: " << "marginalize '" << core::CContainerPrinter::print(marginalize) << "'" << ", condition '" << core::CContainerPrinter::print(condition) << "'"); - return TPriorPtrDoublePr(); + return {}; } if (!this->isNonInformative()) { TDouble10Vec constant; constant[0] = (*m_Constant)[i1[0]]; constant[1] = (*m_Constant)[i1[1]]; - return TPriorPtrDoublePr(TPriorPtr(new CMultivariateConstantPrior(2, constant)), 0.0); + return {boost::make_unique(2, constant), 0.0}; } - return TPriorPtrDoublePr(TPriorPtr(new CMultivariateConstantPrior(2)), 0.0); + return {boost::make_unique(2), 0.0}; } CMultivariateConstantPrior::TDouble10VecDouble10VecPr @@ -171,7 +172,7 @@ CMultivariateConstantPrior::marginalLikelihoodSupport() const { lowest[i] = boost::numeric::bounds::lowest(); highest[i] = boost::numeric::bounds::highest(); } - return std::make_pair(lowest, highest); + return {lowest, highest}; } CMultivariateConstantPrior::TDouble10Vec diff --git a/lib/maths/CMultivariateMultimodalPrior.cc b/lib/maths/CMultivariateMultimodalPrior.cc index 0e2bd96e0d..1d4f237b2a 100644 --- a/lib/maths/CMultivariateMultimodalPrior.cc +++ b/lib/maths/CMultivariateMultimodalPrior.cc @@ -178,7 +178,7 @@ void modeMergeCallback(std::size_t dimension, using TSizeSet = std::set; // Create the new mode. - TMode newMode(targetIndex, seedPrior); + TMode newMode(targetIndex, TPriorPtr(seedPrior->clone())); double wl = 0.0; double wr = 0.0; @@ -253,7 +253,7 @@ void modeMergeCallback(std::size_t dimension, // Add the new mode. LOG_TRACE(<< "Creating mode with index " << targetIndex); - modes.push_back(newMode); + modes.push_back(std::move(newMode)); LOG_TRACE(<< "Merged modes"); } diff --git a/lib/maths/CMultivariateOneOfNPrior.cc b/lib/maths/CMultivariateOneOfNPrior.cc index e45cfcb5af..e38fae3a93 100644 --- a/lib/maths/CMultivariateOneOfNPrior.cc +++ b/lib/maths/CMultivariateOneOfNPrior.cc @@ -136,7 +136,7 @@ bool modelAcceptRestoreTraverser(const SDistributionRestoreParams& params, return false; } - models.emplace_back(weight, model); + models.emplace_back(weight, std::move(model)); return true; } @@ -191,7 +191,7 @@ CMultivariateOneOfNPrior::CMultivariateOneOfNPrior(std::size_t dimension, m_Models.reserve(models.size()); CModelWeight weight(1.0); for (const auto& model : models) { - m_Models.emplace_back(weight, model); + m_Models.emplace_back(weight, TPriorPtr(model->clone())); } } @@ -210,7 +210,7 @@ CMultivariateOneOfNPrior::CMultivariateOneOfNPrior(std::size_t dimension, // Create a new model vector using the specified models and their associated weights. m_Models.reserve(models.size()); for (const auto& model : models) { - m_Models.emplace_back(CModelWeight(model.first), model.second); + m_Models.emplace_back(CModelWeight(model.first), TPriorPtr(model.second->clone())); } } @@ -425,9 +425,9 @@ CMultivariateOneOfNPrior::univariate(const TSize10Vec& marginalize, if (model.second->participatesInModelSelection()) { TUnivariatePriorPtrDoublePr prior(model.second->univariate(marginalize, condition)); if (prior.first == nullptr) { - return TUnivariatePriorPtrDoublePr(); + return {}; } - models.emplace_back(1.0, prior.first); + models.emplace_back(1.0, std::move(prior.first)); weights.push_back(prior.second + model.first.logWeight()); maxWeight.add(weights.back()); Z += std::exp(model.first.logWeight()); @@ -446,7 +446,7 @@ CMultivariateOneOfNPrior::TPriorPtrDoublePr CMultivariateOneOfNPrior::bivariate(const TSize10Vec& marginalize, const TSizeDoublePr10Vec& condition) const { if (m_Dimension == 2) { - return TPriorPtrDoublePr(TPriorPtr(this->clone()), 0.0); + return {TPriorPtr(this->clone()), 0.0}; } TDoublePriorPtrPrVec models; @@ -458,9 +458,9 @@ CMultivariateOneOfNPrior::bivariate(const TSize10Vec& marginalize, if (model.second->participatesInModelSelection()) { TPriorPtrDoublePr prior(model.second->bivariate(marginalize, condition)); if (prior.first == nullptr) { - return TPriorPtrDoublePr(); + return {}; } - models.emplace_back(1.0, prior.first); + models.emplace_back(1.0, std::move(prior.first)); weights.push_back(prior.second + model.first.logWeight()); maxWeight.add(weights.back()); Z += std::exp(model.first.logWeight()); diff --git a/lib/maths/CMultivariateOneOfNPriorFactory.cc b/lib/maths/CMultivariateOneOfNPriorFactory.cc index 0652879b54..25bb7bbbed 100644 --- a/lib/maths/CMultivariateOneOfNPriorFactory.cc +++ b/lib/maths/CMultivariateOneOfNPriorFactory.cc @@ -8,6 +8,8 @@ #include +#include + namespace ml { namespace maths { @@ -16,14 +18,14 @@ CMultivariateOneOfNPriorFactory::nonInformative(std::size_t dimension, maths_t::EDataType dataType, double decayRate, const TPriorPtrVec& models) { - return TPriorPtr(new CMultivariateOneOfNPrior(dimension, models, dataType, decayRate)); + return boost::make_unique(dimension, models, dataType, decayRate); } bool CMultivariateOneOfNPriorFactory::restore(std::size_t dimension, const SDistributionRestoreParams& params, TPriorPtr& ptr, core::CStateRestoreTraverser& traverser) { - ptr.reset(new CMultivariateOneOfNPrior(dimension, params, traverser)); + ptr = boost::make_unique(dimension, params, traverser); return true; } } diff --git a/lib/maths/CNaiveBayes.cc b/lib/maths/CNaiveBayes.cc index 38b351eec3..0347888169 100644 --- a/lib/maths/CNaiveBayes.cc +++ b/lib/maths/CNaiveBayes.cc @@ -125,24 +125,35 @@ CNaiveBayes::CNaiveBayes(const CNaiveBayesFeatureDensity& exemplar, m_ClassConditionalDensities(2) { } -CNaiveBayes::CNaiveBayes(const SDistributionRestoreParams& params, +CNaiveBayes::CNaiveBayes(const CNaiveBayesFeatureDensity& exemplar, + const SDistributionRestoreParams& params, core::CStateRestoreTraverser& traverser) - : m_DecayRate{params.s_DecayRate}, m_ClassConditionalDensities(2) { + : m_DecayRate{params.s_DecayRate}, m_Exemplar{exemplar.clone()}, + m_ClassConditionalDensities(2) { traverser.traverseSubLevel(boost::bind(&CNaiveBayes::acceptRestoreTraverser, this, boost::cref(params), _1)); } +CNaiveBayes::CNaiveBayes(const CNaiveBayes& other) + : m_MinMaxLogLikelihoodToUseFeature{other.m_MinMaxLogLikelihoodToUseFeature}, + m_DecayRate{other.m_DecayRate}, m_Exemplar{other.m_Exemplar->clone()} { + for (const auto& class_ : m_ClassConditionalDensities) { + m_ClassConditionalDensities.emplace(class_.first, class_.second); + } +} + bool CNaiveBayes::acceptRestoreTraverser(const SDistributionRestoreParams& params, core::CStateRestoreTraverser& traverser) { std::size_t label; do { const std::string& name{traverser.name()}; RESTORE_BUILT_IN(CLASS_LABEL_TAG, label) - RESTORE_SETUP_TEARDOWN(CLASS_MODEL_TAG, SClass class_, - traverser.traverseSubLevel(boost::bind( - &SClass::acceptRestoreTraverser, - boost::ref(class_), boost::cref(params), _1)), - m_ClassConditionalDensities.emplace(label, class_)) + RESTORE_SETUP_TEARDOWN( + CLASS_MODEL_TAG, CClass class_, + traverser.traverseSubLevel(boost::bind(&CClass::acceptRestoreTraverser, + boost::ref(class_), + boost::cref(params), _1)), + m_ClassConditionalDensities.emplace(label, std::move(class_))) RESTORE_SETUP_TEARDOWN(MIN_MAX_LOG_LIKELIHOOD_TO_USE_FEATURE_TAG, double value, core::CStringUtils::stringToType(traverser.value(), value), m_MinMaxLogLikelihoodToUseFeature.reset(value)) @@ -153,6 +164,7 @@ bool CNaiveBayes::acceptRestoreTraverser(const SDistributionRestoreParams& param void CNaiveBayes::acceptPersistInserter(core::CStatePersistInserter& inserter) const { using TSizeClassUMapCItr = TSizeClassUMap::const_iterator; using TSizeClassUMapCItrVec = std::vector; + TSizeClassUMapCItrVec classes; classes.reserve(m_ClassConditionalDensities.size()); for (auto i = m_ClassConditionalDensities.begin(); @@ -164,9 +176,10 @@ void CNaiveBayes::acceptPersistInserter(core::CStatePersistInserter& inserter) c for (const auto& class_ : classes) { inserter.insertValue(CLASS_LABEL_TAG, class_->first); inserter.insertLevel(CLASS_MODEL_TAG, - boost::bind(&SClass::acceptPersistInserter, + boost::bind(&CClass::acceptPersistInserter, boost::ref(class_->second), _1)); } + if (m_MinMaxLogLikelihoodToUseFeature) { inserter.insertValue(MIN_MAX_LOG_LIKELIHOOD_TO_USE_FEATURE_TAG, *m_MinMaxLogLikelihoodToUseFeature, @@ -174,6 +187,14 @@ void CNaiveBayes::acceptPersistInserter(core::CStatePersistInserter& inserter) c } } +CNaiveBayes& CNaiveBayes::operator=(const CNaiveBayes& other) { + if (this != &other) { + CNaiveBayes copy{other}; + this->swap(copy); + } + return *this; +} + void CNaiveBayes::swap(CNaiveBayes& other) { std::swap(m_DecayRate, other.m_DecayRate); m_Exemplar.swap(other.m_Exemplar); @@ -187,8 +208,7 @@ bool CNaiveBayes::initialized() const { void CNaiveBayes::initialClassCounts(const TDoubleSizePrVec& counts) { for (const auto& count : counts) { - m_ClassConditionalDensities[count.second] = - SClass{count.first, TFeatureDensityPtrVec{}}; + m_ClassConditionalDensities.emplace(count.second, CClass{count.first}); } } @@ -199,23 +219,23 @@ void CNaiveBayes::addTrainingDataPoint(std::size_t label, const TDouble1VecVec& auto& class_ = m_ClassConditionalDensities[label]; - if (class_.s_ConditionalDensities.empty()) { - class_.s_ConditionalDensities.reserve(x.size()); + if (class_.conditionalDensities().empty()) { + class_.conditionalDensities().reserve(x.size()); std::generate_n( - std::back_inserter(class_.s_ConditionalDensities), x.size(), + std::back_inserter(class_.conditionalDensities()), x.size(), [this]() { return TFeatureDensityPtr{m_Exemplar->clone()}; }); } bool updateCount{false}; for (std::size_t i = 0u; i < x.size(); ++i) { if (x[i].size() > 0) { - class_.s_ConditionalDensities[i]->add(x[i]); + class_.conditionalDensities()[i]->add(x[i]); updateCount = true; } } if (updateCount) { - class_.s_Count += 1.0; + class_.count() += 1.0; } else { LOG_TRACE("Ignoring empty feature vector"); } @@ -223,7 +243,7 @@ void CNaiveBayes::addTrainingDataPoint(std::size_t label, const TDouble1VecVec& void CNaiveBayes::dataType(maths_t::EDataType dataType) { for (auto& class_ : m_ClassConditionalDensities) { - for (auto& density : class_.second.s_ConditionalDensities) { + for (auto& density : class_.second.conditionalDensities()) { density->dataType(dataType); } } @@ -232,8 +252,8 @@ void CNaiveBayes::dataType(maths_t::EDataType dataType) { void CNaiveBayes::propagateForwardsByTime(double time) { double factor{std::exp(-m_DecayRate * time)}; for (auto& class_ : m_ClassConditionalDensities) { - class_.second.s_Count *= factor; - for (auto& density : class_.second.s_ConditionalDensities) { + class_.second.count() *= factor; + for (auto& density : class_.second.conditionalDensities()) { density->propagateForwardsByTime(time); } } @@ -270,7 +290,7 @@ CNaiveBayes::TDoubleSizePrVec CNaiveBayes::classProbabilities(const TDouble1VecV TDoubleSizePrVec p; p.reserve(m_ClassConditionalDensities.size()); for (const auto& class_ : m_ClassConditionalDensities) { - p.emplace_back(CTools::fastLog(class_.second.s_Count), class_.first); + p.emplace_back(CTools::fastLog(class_.second.count()), class_.first); } TDoubleVec logLikelihoods; @@ -279,7 +299,7 @@ CNaiveBayes::TDoubleSizePrVec CNaiveBayes::classProbabilities(const TDouble1VecV TMaxAccumulator maxLogLikelihood; logLikelihoods.clear(); for (const auto& class_ : m_ClassConditionalDensities) { - const auto& density = class_.second.s_ConditionalDensities[i]; + const auto& density = class_.second.conditionalDensities()[i]; double logLikelihood{density->logValue(x[i])}; double logMaximumLikelihood{density->logMaximumValue()}; maxLogLikelihood.add(logLikelihood - logMaximumLikelihood); @@ -323,6 +343,9 @@ std::size_t CNaiveBayes::memoryUsage() const { } uint64_t CNaiveBayes::checksum(uint64_t seed) const { + CChecksum::calculate(seed, m_MinMaxLogLikelihoodToUseFeature); + CChecksum::calculate(seed, m_DecayRate); + CChecksum::calculate(seed, m_Exemplar); return CChecksum::calculate(seed, m_ClassConditionalDensities); } @@ -331,7 +354,7 @@ std::string CNaiveBayes::print() const { result << "\n"; for (const auto& class_ : m_ClassConditionalDensities) { result << "CLASS(" << class_.first << ")\n"; - for (const auto& density : class_.second.s_ConditionalDensities) { + for (const auto& density : class_.second.conditionalDensities()) { result << "---"; result << density->print() << "\n"; } @@ -342,37 +365,43 @@ std::string CNaiveBayes::print() const { bool CNaiveBayes::validate(const TDouble1VecVec& x) const { auto class_ = m_ClassConditionalDensities.begin(); if (class_ != m_ClassConditionalDensities.end() && - class_->second.s_ConditionalDensities.size() > 0 && - class_->second.s_ConditionalDensities.size() != x.size()) { + class_->second.conditionalDensities().size() > 0 && + class_->second.conditionalDensities().size() != x.size()) { LOG_ERROR("Unexpected feature vector: " << core::CContainerPrinter::print(x)); return false; } return true; } -CNaiveBayes::SClass::SClass(double count, const TFeatureDensityPtrVec& conditionalDensities) - : s_Count{count}, s_ConditionalDensities(conditionalDensities) { +CNaiveBayes::CClass::CClass(double count) : m_Count{count} { } -bool CNaiveBayes::SClass::acceptRestoreTraverser(const SDistributionRestoreParams& params, +CNaiveBayes::CClass::CClass(const CClass& other) : m_Count{other.m_Count} { + m_ConditionalDensities.reserve(other.m_ConditionalDensities.size()); + for (const auto& density : other.m_ConditionalDensities) { + m_ConditionalDensities.emplace_back(density->clone()); + } +} + +bool CNaiveBayes::CClass::acceptRestoreTraverser(const SDistributionRestoreParams& params, core::CStateRestoreTraverser& traverser) { do { const std::string& name{traverser.name()}; - RESTORE_BUILT_IN(COUNT_TAG, s_Count) + RESTORE_BUILT_IN(COUNT_TAG, m_Count) RESTORE_SETUP_TEARDOWN(CONDITIONAL_DENSITY_FROM_PRIOR_TAG, - CNaiveBayesFeatureDensityFromPrior tmp, + CNaiveBayesFeatureDensityFromPrior density, traverser.traverseSubLevel(boost::bind( &CNaiveBayesFeatureDensityFromPrior::acceptRestoreTraverser, - boost::ref(tmp), boost::cref(params), _1)), - s_ConditionalDensities.emplace_back(tmp.clone())) + boost::ref(density), boost::cref(params), _1)), + m_ConditionalDensities.emplace_back(density.clone())) // Add other implementations' restore code here. } while (traverser.next()); return true; } -void CNaiveBayes::SClass::acceptPersistInserter(core::CStatePersistInserter& inserter) const { - inserter.insertValue(COUNT_TAG, s_Count, core::CIEEE754::E_SinglePrecision); - for (const auto& density : s_ConditionalDensities) { +void CNaiveBayes::CClass::acceptPersistInserter(core::CStatePersistInserter& inserter) const { + inserter.insertValue(COUNT_TAG, m_Count, core::CIEEE754::E_SinglePrecision); + for (const auto& density : m_ConditionalDensities) { if (dynamic_cast(density.get())) { inserter.insertLevel(CONDITIONAL_DENSITY_FROM_PRIOR_TAG, boost::bind(&CNaiveBayesFeatureDensity::acceptPersistInserter, @@ -383,17 +412,33 @@ void CNaiveBayes::SClass::acceptPersistInserter(core::CStatePersistInserter& ins } } -void CNaiveBayes::SClass::debugMemoryUsage(core::CMemoryUsage::TMemoryUsagePtr mem) const { - core::CMemoryDebug::dynamicSize("s_ConditionalDensities", s_ConditionalDensities, mem); +double CNaiveBayes::CClass::count() const { + return m_Count; +} + +double& CNaiveBayes::CClass::count() { + return m_Count; +} + +const CNaiveBayes::TFeatureDensityPtrVec& CNaiveBayes::CClass::conditionalDensities() const { + return m_ConditionalDensities; +} + +CNaiveBayes::TFeatureDensityPtrVec& CNaiveBayes::CClass::conditionalDensities() { + return m_ConditionalDensities; +} + +void CNaiveBayes::CClass::debugMemoryUsage(core::CMemoryUsage::TMemoryUsagePtr mem) const { + core::CMemoryDebug::dynamicSize("s_ConditionalDensities", m_ConditionalDensities, mem); } -std::size_t CNaiveBayes::SClass::memoryUsage() const { - return core::CMemory::dynamicSize(s_ConditionalDensities); +std::size_t CNaiveBayes::CClass::memoryUsage() const { + return core::CMemory::dynamicSize(m_ConditionalDensities); } -uint64_t CNaiveBayes::SClass::checksum(uint64_t seed) const { - seed = CChecksum::calculate(seed, s_Count); - return CChecksum::calculate(seed, s_ConditionalDensities); +uint64_t CNaiveBayes::CClass::checksum(uint64_t seed) const { + seed = CChecksum::calculate(seed, m_Count); + return CChecksum::calculate(seed, m_ConditionalDensities); } } } diff --git a/lib/maths/COneOfNPrior.cc b/lib/maths/COneOfNPrior.cc index ca1906ce06..7e38123780 100644 --- a/lib/maths/COneOfNPrior.cc +++ b/lib/maths/COneOfNPrior.cc @@ -95,7 +95,7 @@ COneOfNPrior::COneOfNPrior(const TPriorPtrVec& models, maths_t::EDataType dataTy m_Models.reserve(models.size()); CModelWeight weight(1.0); for (const auto& model : models) { - m_Models.emplace_back(weight, model); + m_Models.emplace_back(weight, TPriorPtr(model->clone())); } } @@ -113,7 +113,7 @@ COneOfNPrior::COneOfNPrior(const TDoublePriorPtrPrVec& models, // Create a new model vector using the specified models and their associated weights. m_Models.reserve(models.size()); for (const auto& model : models) { - m_Models.emplace_back(CModelWeight(model.first), model.second); + m_Models.emplace_back(CModelWeight(model.first), TPriorPtr(model.second->clone())); } } @@ -1032,7 +1032,7 @@ bool COneOfNPrior::modelAcceptRestoreTraverser(const SDistributionRestoreParams& return false; } - m_Models.emplace_back(weight, model); + m_Models.emplace_back(weight, std::move(model)); return true; } diff --git a/lib/maths/CPriorStateSerialiser.cc b/lib/maths/CPriorStateSerialiser.cc index 18b1d9883e..e3983c35ed 100644 --- a/lib/maths/CPriorStateSerialiser.cc +++ b/lib/maths/CPriorStateSerialiser.cc @@ -25,7 +25,9 @@ #include #include +#include +#include #include #include @@ -43,40 +45,68 @@ const std::string ONE_OF_N_TAG("e"); const std::string POISSON_TAG("f"); const std::string MULTINOMIAL_TAG("g"); const std::string CONSTANT_TAG("h"); - const std::string EMPTY_STRING; + +//! Implements restore for std::shared_ptr. +template +void doRestore(std::shared_ptr& ptr, core::CStateRestoreTraverser& traverser) { + ptr = std::make_shared(traverser); } -bool CPriorStateSerialiser::operator()(const SDistributionRestoreParams& params, - TPriorPtr& ptr, - core::CStateRestoreTraverser& traverser) const { - size_t numResults(0); +//! Implements restore for std::unique_ptr. +template +void doRestore(std::unique_ptr& ptr, core::CStateRestoreTraverser& traverser) { + ptr = boost::make_unique(traverser); +} + +//! Implements restore for std::shared_ptr. +template +void doRestore(const SDistributionRestoreParams& params, + std::shared_ptr& ptr, + core::CStateRestoreTraverser& traverser) { + ptr = std::make_shared(params, traverser); +} + +//! Implements restore for std::unique_ptr. +template +void doRestore(const SDistributionRestoreParams& params, + std::unique_ptr& ptr, + core::CStateRestoreTraverser& traverser) { + ptr = boost::make_unique(params, traverser); +} + +//! Implements restore into the supplied pointer. +template +bool restore(const SDistributionRestoreParams& params, + PTR& ptr, + core::CStateRestoreTraverser& traverser) { + std::size_t numResults{0}; do { const std::string& name = traverser.name(); if (name == CONSTANT_TAG) { - ptr.reset(new CConstantPrior(traverser)); + doRestore(ptr, traverser); ++numResults; } else if (name == GAMMA_TAG) { - ptr.reset(new CGammaRateConjugate(params, traverser)); + doRestore(params, ptr, traverser); ++numResults; } else if (name == LOG_NORMAL_TAG) { - ptr.reset(new CLogNormalMeanPrecConjugate(params, traverser)); + doRestore(params, ptr, traverser); ++numResults; } else if (name == MULTIMODAL_TAG) { - ptr.reset(new CMultimodalPrior(params, traverser)); + doRestore(params, ptr, traverser); ++numResults; } else if (name == MULTINOMIAL_TAG) { - ptr.reset(new CMultinomialConjugate(params, traverser)); + doRestore(params, ptr, traverser); ++numResults; } else if (name == NORMAL_TAG) { - ptr.reset(new CNormalMeanPrecConjugate(params, traverser)); + doRestore(params, ptr, traverser); ++numResults; } else if (name == ONE_OF_N_TAG) { - ptr.reset(new COneOfNPrior(params, traverser)); + doRestore(params, ptr, traverser); ++numResults; } else if (name == POISSON_TAG) { - ptr.reset(new CPoissonMeanConjugate(params, traverser)); + doRestore(params, ptr, traverser); ++numResults; } else { // Due to the way we divide large state into multiple chunks @@ -95,6 +125,19 @@ bool CPriorStateSerialiser::operator()(const SDistributionRestoreParams& params, return true; } +} + +bool CPriorStateSerialiser::operator()(const SDistributionRestoreParams& params, + TPriorUPtr& ptr, + core::CStateRestoreTraverser& traverser) const { + return restore(params, ptr, traverser); +} + +bool CPriorStateSerialiser::operator()(const SDistributionRestoreParams& params, + TPriorSPtr& ptr, + core::CStateRestoreTraverser& traverser) const { + return restore(params, ptr, traverser); +} void CPriorStateSerialiser::operator()(const CPrior& prior, core::CStatePersistInserter& inserter) const { diff --git a/lib/maths/CSeasonalComponentAdaptiveBucketing.cc b/lib/maths/CSeasonalComponentAdaptiveBucketing.cc index 99ea15b1ea..4bbbfae67c 100644 --- a/lib/maths/CSeasonalComponentAdaptiveBucketing.cc +++ b/lib/maths/CSeasonalComponentAdaptiveBucketing.cc @@ -136,7 +136,7 @@ bool CSeasonalComponentAdaptiveBucketing::initialize(std::size_t n) { if (this->CAdaptiveBucketing::initialize(a, b, n)) { n = this->size(); - m_Buckets.assign(n, SBucket()); + m_Buckets.assign(n, {}); return true; } return false; diff --git a/lib/maths/CSeasonalTime.cc b/lib/maths/CSeasonalTime.cc index 662e2afa8a..31d79fb6f6 100644 --- a/lib/maths/CSeasonalTime.cc +++ b/lib/maths/CSeasonalTime.cc @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -252,11 +253,11 @@ bool CSeasonalTimeStateSerializer::acceptRestoreTraverser(TSeasonalTimePtr& resu do { const std::string& name = traverser.name(); if (name == DIURNAL_TIME_TAG) { - result.reset(new CDiurnalTime); + result = boost::make_unique(); result->fromString(traverser.value()); ++numResults; } else if (name == ARBITRARY_PERIOD_TIME_TAG) { - result.reset(new CGeneralPeriodTime); + result = boost::make_unique(); result->fromString(traverser.value()); ++numResults; } else { diff --git a/lib/maths/CTimeSeriesDecomposition.cc b/lib/maths/CTimeSeriesDecomposition.cc index 77b93b5558..a0f247b406 100644 --- a/lib/maths/CTimeSeriesDecomposition.cc +++ b/lib/maths/CTimeSeriesDecomposition.cc @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include diff --git a/lib/maths/CTimeSeriesDecompositionDetail.cc b/lib/maths/CTimeSeriesDecompositionDetail.cc index 03eee8b95c..f2d9b93d8c 100644 --- a/lib/maths/CTimeSeriesDecompositionDetail.cc +++ b/lib/maths/CTimeSeriesDecompositionDetail.cc @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -415,8 +416,6 @@ CTimeSeriesDecompositionDetail::SNewComponents::SNewComponents(core_t::TTime tim CTimeSeriesDecompositionDetail::CHandler::CHandler() : m_Mediator{nullptr} { } -CTimeSeriesDecompositionDetail::CHandler::~CHandler() { -} void CTimeSeriesDecompositionDetail::CHandler::handle(const SAddValue& /*message*/) { } @@ -481,7 +480,7 @@ CTimeSeriesDecompositionDetail::CPeriodicityTest::CPeriodicityTest(const CPeriod // Note that m_Windows is an array. for (std::size_t i = 0u; !isForForecast && i < other.m_Windows.size(); ++i) { if (other.m_Windows[i]) { - m_Windows[i] = std::make_shared(*other.m_Windows[i]); + m_Windows[i] = boost::make_unique(*other.m_Windows[i]); } } } @@ -782,7 +781,7 @@ CTimeSeriesDecompositionDetail::CCalendarTest::CCalendarTest(const CCalendarTest bool isForForecast) : m_Machine{other.m_Machine}, m_DecayRate{other.m_DecayRate}, m_LastMonth{other.m_LastMonth}, m_Test{!isForForecast && other.m_Test - ? std::make_shared( + ? boost::make_unique( *other.m_Test) : nullptr} { } @@ -796,7 +795,7 @@ bool CTimeSeriesDecompositionDetail::CCalendarTest::acceptRestoreTraverser(core: RESTORE_BUILT_IN(LAST_MONTH_6_3_TAG, m_LastMonth); RESTORE_SETUP_TEARDOWN( CALENDAR_TEST_6_3_TAG, - m_Test = std::make_shared(m_DecayRate), + m_Test = boost::make_unique(m_DecayRate), traverser.traverseSubLevel(boost::bind( &CCalendarCyclicTest::acceptRestoreTraverser, m_Test.get(), _1)), /**/) @@ -914,7 +913,7 @@ std::size_t CTimeSeriesDecompositionDetail::CCalendarTest::memoryUsage() const { std::size_t CTimeSeriesDecompositionDetail::CCalendarTest::extraMemoryOnInitialization() const { static std::size_t result{0}; if (result == 0) { - TCalendarCyclicTestPtr test(new CCalendarCyclicTest(m_DecayRate)); + TCalendarCyclicTestPtr test = boost::make_unique(m_DecayRate); result = core::CMemory::dynamicSize(test); } return result; @@ -934,8 +933,8 @@ void CTimeSeriesDecompositionDetail::CCalendarTest::apply(std::size_t symbol, switch (state) { case CC_TEST: - if (!m_Test) { - m_Test = std::make_shared(m_DecayRate); + if (m_Test == nullptr) { + m_Test = boost::make_unique(m_DecayRate); m_LastMonth = this->month(time) + 2; } break; @@ -983,8 +982,8 @@ CTimeSeriesDecompositionDetail::CComponents::CComponents(const CComponents& othe m_BucketLength{other.m_BucketLength}, m_GainController{other.m_GainController}, m_SeasonalComponentSize{other.m_SeasonalComponentSize}, m_CalendarComponentSize{other.m_CalendarComponentSize}, m_Trend{other.m_Trend}, - m_Seasonal{other.m_Seasonal ? new CSeasonal{*other.m_Seasonal} : nullptr}, - m_Calendar{other.m_Calendar ? new CCalendar{*other.m_Calendar} : nullptr}, + m_Seasonal{other.m_Seasonal ? boost::make_unique(*other.m_Seasonal) : nullptr}, + m_Calendar{other.m_Calendar ? boost::make_unique(*other.m_Calendar) : nullptr}, m_MeanVarianceScale{other.m_MeanVarianceScale}, m_PredictionErrorWithoutTrend{other.m_PredictionErrorWithoutTrend}, m_PredictionErrorWithTrend{other.m_PredictionErrorWithTrend}, @@ -1008,13 +1007,13 @@ bool CTimeSeriesDecompositionDetail::CComponents::acceptRestoreTraverser( &CTrendComponent::acceptRestoreTraverser, &m_Trend, boost::cref(params), _1))) RESTORE_SETUP_TEARDOWN( - SEASONAL_6_3_TAG, m_Seasonal.reset(new CSeasonal), + SEASONAL_6_3_TAG, m_Seasonal = boost::make_unique(), traverser.traverseSubLevel( boost::bind(&CSeasonal::acceptRestoreTraverser, m_Seasonal.get(), m_DecayRate, m_BucketLength, _1)), /**/) RESTORE_SETUP_TEARDOWN( - CALENDAR_6_3_TAG, m_Calendar.reset(new CCalendar), + CALENDAR_6_3_TAG, m_Calendar = boost::make_unique(), traverser.traverseSubLevel( boost::bind(&CCalendar::acceptRestoreTraverser, m_Calendar.get(), m_DecayRate, m_BucketLength, _1)), @@ -1043,13 +1042,13 @@ bool CTimeSeriesDecompositionDetail::CComponents::acceptRestoreTraverser( m_BucketLength, boost::ref(m_Trend), _1)), m_UsingTrendForPrediction = true) RESTORE_SETUP_TEARDOWN( - SEASONAL_OLD_TAG, m_Seasonal.reset(new CSeasonal), + SEASONAL_OLD_TAG, m_Seasonal = boost::make_unique(), traverser.traverseSubLevel( boost::bind(&CSeasonal::acceptRestoreTraverser, m_Seasonal.get(), m_DecayRate, m_BucketLength, _1)), /**/) RESTORE_SETUP_TEARDOWN( - CALENDAR_OLD_TAG, m_Calendar.reset(new CCalendar), + CALENDAR_OLD_TAG, m_Calendar = boost::make_unique(), traverser.traverseSubLevel( boost::bind(&CCalendar::acceptRestoreTraverser, m_Calendar.get(), m_DecayRate, m_BucketLength, _1)), @@ -1206,7 +1205,7 @@ void CTimeSeriesDecompositionDetail::CComponents::handle(const SDetectedSeasonal case SC_NORMAL: case SC_NEW_COMPONENTS: { if (!m_Seasonal) { - m_Seasonal.reset(new CSeasonal); + m_Seasonal = boost::make_unique(); } core_t::TTime time{message.s_Time}; @@ -1248,7 +1247,7 @@ void CTimeSeriesDecompositionDetail::CComponents::handle(const SDetectedCalendar case SC_NORMAL: case SC_NEW_COMPONENTS: { if (!m_Calendar) { - m_Calendar.reset(new CCalendar); + m_Calendar = boost::make_unique(); } core_t::TTime time{message.s_Time}; diff --git a/lib/maths/CTimeSeriesDecompositionStateSerialiser.cc b/lib/maths/CTimeSeriesDecompositionStateSerialiser.cc index 8bfe1a0c64..76f9f50877 100644 --- a/lib/maths/CTimeSeriesDecompositionStateSerialiser.cc +++ b/lib/maths/CTimeSeriesDecompositionStateSerialiser.cc @@ -15,7 +15,9 @@ #include #include +#include +#include #include #include @@ -30,23 +32,49 @@ namespace { // DO NOT change the existing tags if new sub-classes are added. const std::string TIME_SERIES_DECOMPOSITION_TAG("a"); const std::string TIME_SERIES_DECOMPOSITION_STUB_TAG("b"); - const std::string EMPTY_STRING; + +//! Implements restore for std::shared_ptr. +template +void doRestore(std::shared_ptr& ptr) { + ptr = std::make_shared(); } -bool CTimeSeriesDecompositionStateSerialiser:: -operator()(const STimeSeriesDecompositionRestoreParams& params, - TDecompositionPtr& result, - core::CStateRestoreTraverser& traverser) const { - std::size_t numResults = 0; +//! Implements restore for std::unique_ptr. +template +void doRestore(std::unique_ptr& ptr) { + ptr = boost::make_unique(); +} +//! Implements restore for std::shared_ptr. +template +void doRestore(const STimeSeriesDecompositionRestoreParams& params, + std::shared_ptr& ptr, + core::CStateRestoreTraverser& traverser) { + ptr = std::make_shared(params, traverser); +} + +//! Implements restore for std::unique_ptr. +template +void doRestore(const STimeSeriesDecompositionRestoreParams& params, + std::unique_ptr& ptr, + core::CStateRestoreTraverser& traverser) { + ptr = boost::make_unique(params, traverser); +} + +//! Implements restore into the supplied pointer. +template +bool restore(const STimeSeriesDecompositionRestoreParams& params, + PTR& ptr, + core::CStateRestoreTraverser& traverser) { + std::size_t numResults{0}; do { const std::string& name = traverser.name(); if (name == TIME_SERIES_DECOMPOSITION_TAG) { - result.reset(new CTimeSeriesDecomposition(params, traverser)); + doRestore(params, ptr, traverser); ++numResults; } else if (name == TIME_SERIES_DECOMPOSITION_STUB_TAG) { - result.reset(new CTimeSeriesDecompositionStub()); + doRestore(ptr); ++numResults; } else { LOG_ERROR(<< "No decomposition corresponds to name " << traverser.name()); @@ -56,12 +84,27 @@ operator()(const STimeSeriesDecompositionRestoreParams& params, if (numResults != 1) { LOG_ERROR(<< "Expected 1 (got " << numResults << ") decomposition tags"); - result.reset(); + ptr.reset(); return false; } return true; } +} + +bool CTimeSeriesDecompositionStateSerialiser:: +operator()(const STimeSeriesDecompositionRestoreParams& params, + TDecompositionUPtr& ptr, + core::CStateRestoreTraverser& traverser) const { + return restore(params, ptr, traverser); +} + +bool CTimeSeriesDecompositionStateSerialiser:: +operator()(const STimeSeriesDecompositionRestoreParams& params, + TDecompositionSPtr& ptr, + core::CStateRestoreTraverser& traverser) const { + return restore(params, ptr, traverser); +} void CTimeSeriesDecompositionStateSerialiser:: operator()(const CTimeSeriesDecompositionInterface& decomposition, diff --git a/lib/maths/CTimeSeriesDecompositionStub.cc b/lib/maths/CTimeSeriesDecompositionStub.cc index e7249eccaa..be17b61d6c 100644 --- a/lib/maths/CTimeSeriesDecompositionStub.cc +++ b/lib/maths/CTimeSeriesDecompositionStub.cc @@ -7,6 +7,7 @@ #include #include +#include namespace ml { namespace maths { diff --git a/lib/maths/CTimeSeriesModel.cc b/lib/maths/CTimeSeriesModel.cc index 8bde49c498..cbb9b01ab9 100644 --- a/lib/maths/CTimeSeriesModel.cc +++ b/lib/maths/CTimeSeriesModel.cc @@ -26,6 +26,8 @@ #include #include +#include + #include #include #include @@ -53,7 +55,7 @@ using TSizeDoublePr10Vec = core::CSmallVector; using TTail10Vec = core::CSmallVector; using TOptionalSize = boost::optional; using TMeanAccumulator = CBasicStatistics::SSampleMean::TAccumulator; -using TChangeDetectorPtr = std::shared_ptr; +using TChangeDetectorPtr = std::unique_ptr; using TMultivariatePriorCPtrSizePr1Vec = CTimeSeriesCorrelations::TMultivariatePriorCPtrSizePr1Vec; //! The decay rate controllers we maintain. @@ -594,14 +596,14 @@ CUnivariateTimeSeriesModel::CUnivariateTimeSeriesModel(const CModelParams& param bool modelAnomalies) : CModel(params), m_Id(id), m_IsNonNegative(false), m_IsForecastable(true), m_TrendModel(trendModel.clone()), m_ResidualModel(residualModel.clone()), - m_AnomalyModel(modelAnomalies ? std::make_shared( + m_AnomalyModel(modelAnomalies ? boost::make_unique( params.bucketLength(), params.decayRate()) - : TAnomalyModelPtr()), + : nullptr), m_CurrentChangeInterval(0), m_SlidingWindow(SLIDING_WINDOW_SIZE), m_Correlations(nullptr) { if (controllers) { - m_Controllers = std::make_shared(*controllers); + m_Controllers = boost::make_unique(*controllers); } } @@ -1174,7 +1176,7 @@ bool CUnivariateTimeSeriesModel::acceptRestoreTraverser(const SModelRestoreParam RESTORE(RNG_6_3_TAG, m_Rng.fromString(traverser.value())) RESTORE_SETUP_TEARDOWN( CONTROLLER_6_3_TAG, - m_Controllers = std::make_shared(), + m_Controllers = boost::make_unique(), core::CPersistUtils::restore(CONTROLLER_6_3_TAG, *m_Controllers, traverser), /**/) RESTORE(TREND_MODEL_6_3_TAG, traverser.traverseSubLevel(boost::bind( @@ -1187,7 +1189,7 @@ bool CUnivariateTimeSeriesModel::acceptRestoreTraverser(const SModelRestoreParam boost::ref(m_ResidualModel), _1))) RESTORE_SETUP_TEARDOWN( ANOMALY_MODEL_6_3_TAG, - m_AnomalyModel = std::make_shared(), + m_AnomalyModel = boost::make_unique(), traverser.traverseSubLevel( boost::bind(&CTimeSeriesAnomalyModel::acceptRestoreTraverser, m_AnomalyModel.get(), boost::cref(params), _1)), @@ -1197,7 +1199,7 @@ bool CUnivariateTimeSeriesModel::acceptRestoreTraverser(const SModelRestoreParam RESTORE_BUILT_IN(CURRENT_CHANGE_INTERVAL_6_3_TAG, m_CurrentChangeInterval) RESTORE_SETUP_TEARDOWN( CHANGE_DETECTOR_6_3_TAG, - m_ChangeDetector = std::make_shared( + m_ChangeDetector = boost::make_unique( m_TrendModel, m_ResidualModel), traverser.traverseSubLevel(boost::bind( &CUnivariateTimeSeriesChangeDetector::acceptRestoreTraverser, @@ -1216,7 +1218,7 @@ bool CUnivariateTimeSeriesModel::acceptRestoreTraverser(const SModelRestoreParam RESTORE_BOOL(IS_FORECASTABLE_OLD_TAG, m_IsForecastable) RESTORE_SETUP_TEARDOWN( CONTROLLER_OLD_TAG, - m_Controllers = std::make_shared(), + m_Controllers = boost::make_unique(), core::CPersistUtils::restore(CONTROLLER_OLD_TAG, *m_Controllers, traverser), /**/) RESTORE(TREND_OLD_TAG, traverser.traverseSubLevel(boost::bind( @@ -1229,7 +1231,7 @@ bool CUnivariateTimeSeriesModel::acceptRestoreTraverser(const SModelRestoreParam boost::ref(m_ResidualModel), _1))) RESTORE_SETUP_TEARDOWN( ANOMALY_MODEL_OLD_TAG, - m_AnomalyModel = std::make_shared(), + m_AnomalyModel = boost::make_unique(), traverser.traverseSubLevel( boost::bind(&CTimeSeriesAnomalyModel::acceptRestoreTraverser, m_AnomalyModel.get(), boost::cref(params), _1)), @@ -1321,19 +1323,19 @@ CUnivariateTimeSeriesModel::CUnivariateTimeSeriesModel(const CUnivariateTimeSeri m_IsForecastable(other.m_IsForecastable), m_Rng(other.m_Rng), m_TrendModel(other.m_TrendModel->clone()), m_ResidualModel(other.m_ResidualModel->clone()), - m_AnomalyModel(!isForForecast && other.m_AnomalyModel - ? std::make_shared(*other.m_AnomalyModel) - : TAnomalyModelPtr()), + m_AnomalyModel(!isForForecast && other.m_AnomalyModel != nullptr + ? boost::make_unique(*other.m_AnomalyModel) + : nullptr), m_CandidateChangePoint(other.m_CandidateChangePoint), m_CurrentChangeInterval(other.m_CurrentChangeInterval), - m_ChangeDetector(!isForForecast && other.m_ChangeDetector - ? std::make_shared( - *other.m_ChangeDetector) - : TChangeDetectorPtr()), + m_ChangeDetector( + !isForForecast && other.m_ChangeDetector != nullptr + ? boost::make_unique(*other.m_ChangeDetector) + : nullptr), m_SlidingWindow(!isForForecast ? other.m_SlidingWindow : TTimeDoublePrCBuf{}), m_Correlations(nullptr) { if (!isForForecast && other.m_Controllers != nullptr) { - m_Controllers = std::make_shared(*other.m_Controllers); + m_Controllers = boost::make_unique(*other.m_Controllers); } } @@ -1354,7 +1356,7 @@ CUnivariateTimeSeriesModel::testAndApplyChange(const CModelAddSamplesParams& par m_CurrentChangeInterval += this->params().bucketLength(); if (this->params().testForChange(m_CurrentChangeInterval)) { LOG_TRACE(<< "Starting to test for change at " << time); - m_ChangeDetector = std::make_shared( + m_ChangeDetector = boost::make_unique( m_TrendModel, m_ResidualModel, minimumTimeToDetect, maximumTimeToTest); m_CurrentChangeInterval = 0; } @@ -1716,9 +1718,10 @@ void CTimeSeriesCorrelations::refresh(const CTimeSeriesCorrelateModelAllocator& for (/**/; i < missing.size() && m_CorrelationDistributionModels.size() < nextChunk; ++i) { - m_CorrelationDistributionModels.insert( - {missing[i], - {allocator.newPrior(), correlationCoeffs[missingRank[i]]}}); + m_CorrelationDistributionModels.emplace( + missing[i], TMultivariatePriorPtrDoublePr{ + allocator.newPrior(), + correlationCoeffs[missingRank[i]]}); } } } @@ -1786,7 +1789,7 @@ bool CTimeSeriesCorrelations::restoreCorrelationModels(const SDistributionRestor CORRELATION_MODEL_TAG, TSizeSizePrMultivariatePriorPtrDoublePrPr prior, traverser.traverseSubLevel(boost::bind(&restore, boost::cref(params), boost::ref(prior), _1)), - m_CorrelationDistributionModels.insert(prior)) + m_CorrelationDistributionModels.insert(std::move(prior))) } while (traverser.next()); return true; } @@ -1824,7 +1827,7 @@ bool CTimeSeriesCorrelations::restore(const SDistributionRestoreParams& params, return true; } -void CTimeSeriesCorrelations::persist(const TSizeSizePrMultivariatePriorPtrDoublePrPr& model, +void CTimeSeriesCorrelations::persist(const TConstSizeSizePrMultivariatePriorPtrDoublePrPr& model, core::CStatePersistInserter& inserter) { inserter.insertValue(FIRST_CORRELATE_ID_TAG, model.first.first); inserter.insertValue(SECOND_CORRELATE_ID_TAG, model.first.second); @@ -1954,13 +1957,13 @@ CMultivariateTimeSeriesModel::CMultivariateTimeSeriesModel( const TDecayRateController2Ary* controllers, bool modelAnomalies) : CModel(params), m_IsNonNegative(false), m_ResidualModel(residualModel.clone()), - m_AnomalyModel(modelAnomalies ? std::make_shared( + m_AnomalyModel(modelAnomalies ? boost::make_unique( params.bucketLength(), params.decayRate()) - : TAnomalyModelPtr()), + : nullptr), m_SlidingWindow(SLIDING_WINDOW_SIZE) { if (controllers) { - m_Controllers = std::make_shared(*controllers); + m_Controllers = boost::make_unique(*controllers); } for (std::size_t d = 0u; d < this->dimension(); ++d) { m_TrendModel.emplace_back(trend.clone()); @@ -1970,12 +1973,12 @@ CMultivariateTimeSeriesModel::CMultivariateTimeSeriesModel( CMultivariateTimeSeriesModel::CMultivariateTimeSeriesModel(const CMultivariateTimeSeriesModel& other) : CModel(other.params()), m_IsNonNegative(other.m_IsNonNegative), m_ResidualModel(other.m_ResidualModel->clone()), - m_AnomalyModel(other.m_AnomalyModel - ? std::make_shared(*other.m_AnomalyModel) - : TAnomalyModelPtr()), + m_AnomalyModel(other.m_AnomalyModel != nullptr + ? boost::make_unique(*other.m_AnomalyModel) + : nullptr), m_SlidingWindow(other.m_SlidingWindow) { if (other.m_Controllers) { - m_Controllers = std::make_shared(*other.m_Controllers); + m_Controllers = boost::make_unique(*other.m_Controllers); } m_TrendModel.reserve(other.m_TrendModel.size()); for (const auto& trend : other.m_TrendModel) { @@ -1990,6 +1993,9 @@ CMultivariateTimeSeriesModel::CMultivariateTimeSeriesModel(const SModelRestorePa this, boost::cref(params), _1)); } +CMultivariateTimeSeriesModel::~CMultivariateTimeSeriesModel() { +} + std::size_t CMultivariateTimeSeriesModel::identifier() const { return 0; } @@ -2016,7 +2022,7 @@ void CMultivariateTimeSeriesModel::modelCorrelations(CTimeSeriesCorrelations& /* } TSize2Vec1Vec CMultivariateTimeSeriesModel::correlates() const { - return TSize2Vec1Vec(); + return {}; } void CMultivariateTimeSeriesModel::addBucketValue(const TTimeDouble2VecSizeTrVec& /*value*/) { @@ -2433,7 +2439,7 @@ bool CMultivariateTimeSeriesModel::acceptRestoreTraverser(const SModelRestorePar RESTORE(RNG_6_3_TAG, m_Rng.fromString(traverser.value())) RESTORE_SETUP_TEARDOWN( CONTROLLER_6_3_TAG, - m_Controllers = std::make_shared(), + m_Controllers = boost::make_unique(), core::CPersistUtils::restore(CONTROLLER_6_3_TAG, *m_Controllers, traverser), /**/) RESTORE_SETUP_TEARDOWN( @@ -2449,7 +2455,7 @@ bool CMultivariateTimeSeriesModel::acceptRestoreTraverser(const SModelRestorePar boost::ref(m_ResidualModel), _1))) RESTORE_SETUP_TEARDOWN( ANOMALY_MODEL_6_3_TAG, - m_AnomalyModel = std::make_shared(), + m_AnomalyModel = boost::make_unique(), traverser.traverseSubLevel( boost::bind(&CTimeSeriesAnomalyModel::acceptRestoreTraverser, m_AnomalyModel.get(), boost::cref(params), _1)), @@ -2464,7 +2470,7 @@ bool CMultivariateTimeSeriesModel::acceptRestoreTraverser(const SModelRestorePar RESTORE_BOOL(IS_NON_NEGATIVE_OLD_TAG, m_IsNonNegative) RESTORE_SETUP_TEARDOWN( CONTROLLER_OLD_TAG, - m_Controllers = std::make_shared(), + m_Controllers = boost::make_unique(), core::CPersistUtils::restore(CONTROLLER_6_3_TAG, *m_Controllers, traverser), /**/) RESTORE_SETUP_TEARDOWN( @@ -2480,7 +2486,7 @@ bool CMultivariateTimeSeriesModel::acceptRestoreTraverser(const SModelRestorePar boost::ref(m_ResidualModel), _1))) RESTORE_SETUP_TEARDOWN( ANOMALY_MODEL_OLD_TAG, - m_AnomalyModel = std::make_shared(), + m_AnomalyModel = boost::make_unique(), traverser.traverseSubLevel( boost::bind(&CTimeSeriesAnomalyModel::acceptRestoreTraverser, m_AnomalyModel.get(), boost::cref(params), _1)), diff --git a/lib/maths/CTrendComponent.cc b/lib/maths/CTrendComponent.cc index 882cd62842..56c278d9ac 100644 --- a/lib/maths/CTrendComponent.cc +++ b/lib/maths/CTrendComponent.cc @@ -72,11 +72,14 @@ TOptionalDoubleDoublePr confidenceInterval(double prediction, double variance, d return TOptionalDoubleDoublePr{}; } +CNaiveBayesFeatureDensityFromPrior naiveBayesExemplar(double decayRate) { + return CNaiveBayesFeatureDensityFromPrior{CNormalMeanPrecConjugate::nonInformativePrior( + maths_t::E_ContinuousData, TIME_SCALES[NUMBER_MODELS - 1] * decayRate)}; +} + CNaiveBayes initialProbabilityOfChangeModel(double decayRate) { - decayRate *= TIME_SCALES[NUMBER_MODELS - 1]; - return CNaiveBayes{CNaiveBayesFeatureDensityFromPrior{CNormalMeanPrecConjugate::nonInformativePrior( - maths_t::E_ContinuousData, decayRate)}, - decayRate, -20.0}; + return CNaiveBayes{naiveBayesExemplar(decayRate), + TIME_SCALES[NUMBER_MODELS - 1] * decayRate, -20.0}; } CNormalMeanPrecConjugate initialMagnitudeOfChangeModel(double decayRate) { @@ -160,7 +163,8 @@ bool CTrendComponent::acceptRestoreTraverser(const SDistributionRestoreParams& p RESTORE(VALUE_MOMENTS_TAG, m_ValueMoments.fromDelimited(traverser.value())) RESTORE_BUILT_IN(TIME_OF_LAST_LEVEL_CHANGE_TAG, m_TimeOfLastLevelChange) RESTORE_NO_ERROR(PROBABILITY_OF_LEVEL_CHANGE_MODEL_TAG, - m_ProbabilityOfLevelChangeModel = CNaiveBayes(params, traverser)) + m_ProbabilityOfLevelChangeModel = std::move(CNaiveBayes( + naiveBayesExemplar(m_DefaultDecayRate), params, traverser))) RESTORE_NO_ERROR(MAGNITUDE_OF_LEVEL_CHANGE_MODEL_TAG, m_MagnitudeOfLevelChangeModel = CNormalMeanPrecConjugate(params, traverser)) diff --git a/lib/maths/unittest/CMultimodalPriorTest.cc b/lib/maths/unittest/CMultimodalPriorTest.cc index 8fb8d7d651..dbfa7921b8 100644 --- a/lib/maths/unittest/CMultimodalPriorTest.cc +++ b/lib/maths/unittest/CMultimodalPriorTest.cc @@ -43,7 +43,7 @@ namespace { using TDoubleVec = std::vector; using TDoubleDoublePr = std::pair; using TDoubleDoublePrVec = std::vector; -using TPriorPtr = std::shared_ptr; +using TPriorPtr = std::unique_ptr; using CGammaRateConjugate = CPriorTestInterfaceMixin; using CLogNormalMeanPrecConjugate = CPriorTestInterfaceMixin; using CNormalMeanPrecConjugate = CPriorTestInterfaceMixin; diff --git a/lib/maths/unittest/CNaiveBayesTest.cc b/lib/maths/unittest/CNaiveBayesTest.cc index b0de6d00d0..da3564d6b7 100644 --- a/lib/maths/unittest/CNaiveBayesTest.cc +++ b/lib/maths/unittest/CNaiveBayesTest.cc @@ -234,7 +234,7 @@ void CNaiveBayesTest::testMemoryUsage() { // Check invariants. using TMemoryUsagePtr = std::unique_ptr; - using TNaiveBayesPtr = std::shared_ptr; + using TNaiveBayesPtr = std::unique_ptr; test::CRandomNumbers rng; @@ -306,7 +306,8 @@ void CNaiveBayesTest::testPersist() { core::CRapidXmlStateRestoreTraverser traverser(parser); maths::SDistributionRestoreParams params{maths_t::E_ContinuousData, 0.1, 0.0, 0.0, 0.0}; - maths::CNaiveBayes restoredNb{params, traverser}; + maths::CNaiveBayes restoredNb{maths::CNaiveBayesFeatureDensityFromPrior(normal), + params, traverser}; CPPUNIT_ASSERT_EQUAL(origNb.checksum(), restoredNb.checksum()); diff --git a/lib/maths/unittest/COneOfNPriorTest.cc b/lib/maths/unittest/COneOfNPriorTest.cc index 7f2bb5fe64..d48bc418d0 100644 --- a/lib/maths/unittest/COneOfNPriorTest.cc +++ b/lib/maths/unittest/COneOfNPriorTest.cc @@ -48,7 +48,7 @@ using TDoubleVec = std::vector; using TDoubleDoublePr = std::pair; using TDoubleDoublePrVec = std::vector; using TMeanAccumulator = maths::CBasicStatistics::SSampleMean::TAccumulator; -using TPriorPtr = std::shared_ptr; +using TPriorPtr = std::unique_ptr; using TPriorPtrVec = std::vector; using TOptionalDouble = boost::optional; using CGammaRateConjugate = CPriorTestInterfaceMixin; @@ -64,7 +64,7 @@ COneOfNPrior::TPriorPtrVec clone(const TPriorPtrVec& models, COneOfNPrior::TPriorPtrVec result; result.reserve(models.size()); for (std::size_t i = 0u; i < models.size(); ++i) { - result.push_back(COneOfNPrior::TPriorPtr(models[i]->clone())); + result.push_back(TPriorPtr(models[i]->clone())); if (decayRate) { result.back()->decayRate(*decayRate); } @@ -505,7 +505,7 @@ void COneOfNPriorTest::testModelSelection() { maths::CNormalMeanPrecConjugate normal = maths::CNormalMeanPrecConjugate::nonInformativePrior(maths_t::E_ContinuousData); maths::COneOfNPrior::TPriorPtrVec mode; - mode.push_back(COneOfNPrior::TPriorPtr(normal.clone())); + mode.push_back(TPriorPtr(normal.clone())); models.push_back(TPriorPtr(new maths::CMultimodalPrior( maths_t::E_ContinuousData, clusterer, maths::COneOfNPrior(mode, maths_t::E_ContinuousData)))); diff --git a/lib/maths/unittest/CTimeSeriesChangeDetectorTest.cc b/lib/maths/unittest/CTimeSeriesChangeDetectorTest.cc index 27871b0f7c..5db53fdeb8 100644 --- a/lib/maths/unittest/CTimeSeriesChangeDetectorTest.cc +++ b/lib/maths/unittest/CTimeSeriesChangeDetectorTest.cc @@ -41,7 +41,6 @@ using TTimeDoublePr = std::pair; using TTimeDoublePrCBuf = boost::circular_buffer; using TDecompositionPtr = std::shared_ptr; using TPriorPtr = std::shared_ptr; -using TPriorPtrVec = std::vector; core_t::TTime BUCKET_LENGTH{1800}; const double DECAY_RATE{0.0002}; @@ -54,7 +53,7 @@ TPriorPtr makeResidualModel() { maths::CNormalMeanPrecConjugate normal{maths::CNormalMeanPrecConjugate::nonInformativePrior( maths_t::E_ContinuousData, DECAY_RATE)}; - TPriorPtrVec mode; + maths::COneOfNPrior::TPriorPtrVec mode; mode.reserve(3u); mode.emplace_back(gamma.clone()); mode.emplace_back(lognormal.clone()); @@ -70,7 +69,7 @@ TPriorPtr makeResidualModel() { maths::CMultimodalPrior multimodal{maths_t::E_ContinuousData, clusterer, modePrior, DECAY_RATE}; - TPriorPtrVec models; + maths::COneOfNPrior::TPriorPtrVec models; mode.emplace_back(gamma.clone()); mode.emplace_back(lognormal.clone()); mode.emplace_back(normal.clone()); diff --git a/lib/maths/unittest/CTimeSeriesModelTest.cc b/lib/maths/unittest/CTimeSeriesModelTest.cc index dabedade13..fce3067ebb 100644 --- a/lib/maths/unittest/CTimeSeriesModelTest.cc +++ b/lib/maths/unittest/CTimeSeriesModelTest.cc @@ -1101,14 +1101,16 @@ void CTimeSeriesModelTest::testProbability() { LOG_DEBUG(<< "Univariate"); { - maths::CUnivariateTimeSeriesModel models[]{ - maths::CUnivariateTimeSeriesModel{modelParams(bucketLength), 1, - maths::CTimeSeriesDecompositionStub{}, - univariateNormal(), 0, false}, - maths::CUnivariateTimeSeriesModel{ - modelParams(bucketLength), 1, - maths::CTimeSeriesDecomposition{24.0 * DECAY_RATE, bucketLength}, - univariateNormal(), nullptr, false}}; + maths::CUnivariateTimeSeriesModel model0{ + modelParams(bucketLength), 1, maths::CTimeSeriesDecompositionStub{}, + univariateNormal(), 0, false}; + maths::CUnivariateTimeSeriesModel model1{ + modelParams(bucketLength), + 1, + maths::CTimeSeriesDecomposition{24.0 * DECAY_RATE, bucketLength}, + univariateNormal(), + nullptr, + false}; TDoubleVec samples; rng.generateNormalSamples(10.0, 4.0, 1000, samples); @@ -1120,9 +1122,9 @@ void CTimeSeriesModelTest::testProbability() { for (auto sample : samples) { double trend{5.0 + 5.0 * std::sin(boost::math::double_constants::two_pi * static_cast(time) / 86400.0)}; - models[0].addSamples(addSampleParams(weight), - {core::make_triple(time, TDouble2Vec{sample}, TAG)}); - models[1].addSamples( + model0.addSamples(addSampleParams(weight), + {core::make_triple(time, TDouble2Vec{sample}, TAG)}); + model1.addSamples( addSampleParams(weight), {core::make_triple(time, TDouble2Vec{trend + sample}, TAG)}); time += bucketLength; @@ -1158,12 +1160,12 @@ void CTimeSeriesModelTest::testProbability() { weight_[i] = weight[i][0]; } double lb[2], ub[2]; - models[0].residualModel().probabilityOfLessLikelySamples( + model0.residualModel().probabilityOfLessLikelySamples( calculation, sample, {weight_}, lb[0], ub[0], expectedTail[0]); - models[1].residualModel().probabilityOfLessLikelySamples( + model1.residualModel().probabilityOfLessLikelySamples( calculation, - {models[1].trendModel().detrend(time, sample[0], confidence)}, + {model1.trendModel().detrend(time, sample[0], confidence)}, {weight_}, lb[1], ub[1], expectedTail[1]); expectedProbability[0] = (lb[0] + ub[0]) / 2.0; expectedProbability[1] = (lb[1] + ub[1]) / 2.0; @@ -1179,12 +1181,12 @@ void CTimeSeriesModelTest::testProbability() { .addWeights(weight); bool conditional; TSize1Vec mostAnomalousCorrelate; - models[0].probability(params, time_, {sample}, - probability[0], tail[0], conditional, - mostAnomalousCorrelate); - models[1].probability(params, time_, {sample}, - probability[1], tail[1], conditional, - mostAnomalousCorrelate); + model0.probability(params, time_, {sample}, + probability[0], tail[0], conditional, + mostAnomalousCorrelate); + model1.probability(params, time_, {sample}, + probability[1], tail[1], conditional, + mostAnomalousCorrelate); } CPPUNIT_ASSERT_EQUAL(expectedProbability[0], probability[0]); @@ -1199,14 +1201,13 @@ void CTimeSeriesModelTest::testProbability() { LOG_DEBUG(<< "Multivariate"); { - maths::CMultivariateTimeSeriesModel models[]{ - maths::CMultivariateTimeSeriesModel{modelParams(bucketLength), - maths::CTimeSeriesDecompositionStub{}, - multivariateNormal(), 0, false}, - maths::CMultivariateTimeSeriesModel{ - modelParams(bucketLength), - maths::CTimeSeriesDecomposition{24.0 * DECAY_RATE, bucketLength}, - multivariateNormal(), nullptr, false}}; + maths::CMultivariateTimeSeriesModel model0{ + modelParams(bucketLength), maths::CTimeSeriesDecompositionStub{}, + multivariateNormal(), 0, false}; + maths::CMultivariateTimeSeriesModel model1{ + modelParams(bucketLength), + maths::CTimeSeriesDecomposition{24.0 * DECAY_RATE, bucketLength}, + multivariateNormal(), nullptr, false}; TDoubleVecVec samples; rng.generateMultivariateNormalSamples( @@ -1218,15 +1219,15 @@ void CTimeSeriesModelTest::testProbability() { TDouble2VecWeightsAryVec weight{maths_t::CUnitWeights::unit(3)}; for (auto& sample : samples) { TDouble2Vec sample_(sample); - models[0].addSamples(addSampleParams(weight), - {core::make_triple(time, sample_, TAG)}); + model0.addSamples(addSampleParams(weight), + {core::make_triple(time, sample_, TAG)}); double trend{5.0 + 5.0 * std::sin(boost::math::double_constants::two_pi * static_cast(time) / 86400.0)}; for (auto& component : sample_) { component += trend; } - models[1].addSamples(addSampleParams(weight), - {core::make_triple(time, sample_, TAG)}); + model1.addSamples(addSampleParams(weight), + {core::make_triple(time, sample_, TAG)}); time += bucketLength; } } @@ -1261,15 +1262,15 @@ void CTimeSeriesModelTest::testProbability() { weight_[i] = weight[i]; } double lb[2], ub[2]; - models[0].residualModel().probabilityOfLessLikelySamples( + model0.residualModel().probabilityOfLessLikelySamples( calculation, {TDouble10Vec(sample)}, {weight_}, lb[0], ub[0], expectedTail[0]); TDouble10Vec detrended; for (std::size_t j = 0u; j < sample.size(); ++j) { - detrended.push_back(models[1].trendModel()[j]->detrend( + detrended.push_back(model1.trendModel()[j]->detrend( time, sample[j], confidence)); } - models[1].residualModel().probabilityOfLessLikelySamples( + model1.residualModel().probabilityOfLessLikelySamples( calculation, {detrended}, {weight_}, lb[1], ub[1], expectedTail[1]); expectedProbability[0] = (lb[0] + ub[0]) / 2.0; @@ -1286,12 +1287,12 @@ void CTimeSeriesModelTest::testProbability() { .addWeights(weight); bool conditional; TSize1Vec mostAnomalousCorrelate; - models[0].probability(params, time_, {sample}, - probability[0], tail[0], conditional, - mostAnomalousCorrelate); - models[1].probability(params, time_, {sample}, - probability[1], tail[1], conditional, - mostAnomalousCorrelate); + model0.probability(params, time_, {sample}, + probability[0], tail[0], conditional, + mostAnomalousCorrelate); + model1.probability(params, time_, {sample}, + probability[1], tail[1], conditional, + mostAnomalousCorrelate); } CPPUNIT_ASSERT_EQUAL(expectedProbability[0], probability[0]); @@ -1788,21 +1789,22 @@ void CTimeSeriesModelTest::testAddSamplesWithCorrelations() { maths::CTimeSeriesDecomposition trend{DECAY_RATE, bucketLength}; maths::CTimeSeriesCorrelations correlations{MINIMUM_SIGNIFICANT_CORRELATION, DECAY_RATE}; maths::CNormalMeanPrecConjugate prior{univariateNormal()}; - maths::CUnivariateTimeSeriesModel models[]{ - {modelParams(bucketLength), 0, trend, prior, nullptr}, - {modelParams(bucketLength), 1, trend, prior, nullptr}}; - models[0].modelCorrelations(correlations); - models[1].modelCorrelations(correlations); + maths::CUnivariateTimeSeriesModel model0{modelParams(bucketLength), 0, + trend, prior, nullptr}; + maths::CUnivariateTimeSeriesModel model1{modelParams(bucketLength), 1, + trend, prior, nullptr}; + model0.modelCorrelations(correlations); + model1.modelCorrelations(correlations); CTimeSeriesCorrelateModelAllocator allocator; TDouble2VecWeightsAryVec weights{maths_t::CUnitWeights::unit(1)}; core_t::TTime time{0}; for (auto sample : samples) { correlations.refresh(allocator); - models[0].addSamples(addSampleParams(weights), - {core::make_triple(time, TDouble2Vec{sample[0]}, TAG)}); - models[1].addSamples(addSampleParams(weights), - {core::make_triple(time, TDouble2Vec{sample[1]}, TAG)}); + model0.addSamples(addSampleParams(weights), + {core::make_triple(time, TDouble2Vec{sample[0]}, TAG)}); + model1.addSamples(addSampleParams(weights), + {core::make_triple(time, TDouble2Vec{sample[1]}, TAG)}); correlations.processSamples(); time += bucketLength; } diff --git a/lib/model/CAnomalyDetectorModel.cc b/lib/model/CAnomalyDetectorModel.cc index 88d3730a3a..792d6aae70 100644 --- a/lib/model/CAnomalyDetectorModel.cc +++ b/lib/model/CAnomalyDetectorModel.cc @@ -478,10 +478,23 @@ const core_t::TTime CAnomalyDetectorModel::TIME_UNSET(-1); const std::string CAnomalyDetectorModel::EMPTY_STRING; CAnomalyDetectorModel::SFeatureModels::SFeatureModels(model_t::EFeature feature, - TMathsModelPtr newModel) + TMathsModelSPtr newModel) : s_Feature(feature), s_NewModel(newModel) { } +CAnomalyDetectorModel::SFeatureModels::SFeatureModels(SFeatureModels&& other) + : s_Feature(other.s_Feature), s_NewModel(std::move(other.s_NewModel)), + s_Models(std::move(other.s_Models)) { +} + +CAnomalyDetectorModel::SFeatureModels& CAnomalyDetectorModel::SFeatureModels:: +operator=(SFeatureModels&& other) { + s_Feature = other.s_Feature; + s_NewModel = std::move(other.s_NewModel); + s_Models = std::move(other.s_Models); + return *this; +} + bool CAnomalyDetectorModel::SFeatureModels::acceptRestoreTraverser(const SModelParams& params_, core::CStateRestoreTraverser& traverser) { maths_t::EDataType dataType{s_NewModel->dataType()}; @@ -490,13 +503,13 @@ bool CAnomalyDetectorModel::SFeatureModels::acceptRestoreTraverser(const SModelP params_.distributionRestoreParams(dataType)}; do { if (traverser.name() == MODEL_TAG) { - TMathsModelPtr prior; + TMathsModelUPtr model; if (!traverser.traverseSubLevel( boost::bind(maths::CModelStateSerialiser(), - boost::cref(params), boost::ref(prior), _1))) { + boost::cref(params), boost::ref(model), _1))) { return false; } - s_Models.push_back(prior); + s_Models.push_back(std::move(model)); } } while (traverser.next()); return true; @@ -519,10 +532,24 @@ std::size_t CAnomalyDetectorModel::SFeatureModels::memoryUsage() const { return core::CMemory::dynamicSize(s_NewModel) + core::CMemory::dynamicSize(s_Models); } -CAnomalyDetectorModel::SFeatureCorrelateModels::SFeatureCorrelateModels(model_t::EFeature feature, - TMultivariatePriorPtr modelPrior, - TCorrelationsPtr model) - : s_Feature(feature), s_ModelPrior(modelPrior), s_Models(model->clone()) { +CAnomalyDetectorModel::SFeatureCorrelateModels::SFeatureCorrelateModels( + model_t::EFeature feature, + const TMultivariatePriorSPtr& modelPrior, + TCorrelationsPtr&& model) + : s_Feature(feature), s_ModelPrior(modelPrior), s_Models(std::move(model)) { +} + +CAnomalyDetectorModel::SFeatureCorrelateModels::SFeatureCorrelateModels(SFeatureCorrelateModels&& other) + : s_Feature(other.s_Feature), s_ModelPrior(std::move(other.s_ModelPrior)), + s_Models(std::move(other.s_Models)) { +} + +CAnomalyDetectorModel::SFeatureCorrelateModels& CAnomalyDetectorModel::SFeatureCorrelateModels:: +operator=(SFeatureCorrelateModels&& other) { + s_Feature = other.s_Feature; + s_ModelPrior = std::move(other.s_ModelPrior); + s_Models = std::move(other.s_Models); + return *this; } bool CAnomalyDetectorModel::SFeatureCorrelateModels::acceptRestoreTraverser( @@ -586,13 +613,13 @@ std::size_t CAnomalyDetectorModel::CTimeSeriesCorrelateModelAllocator::chunkSize return 500; } -CAnomalyDetectorModel::TMultivariatePriorPtr +CAnomalyDetectorModel::CTimeSeriesCorrelateModelAllocator::TMultivariatePriorUPtr CAnomalyDetectorModel::CTimeSeriesCorrelateModelAllocator::newPrior() const { - return TMultivariatePriorPtr(m_PrototypePrior->clone()); + return TMultivariatePriorUPtr(m_PrototypePrior->clone()); } void CAnomalyDetectorModel::CTimeSeriesCorrelateModelAllocator::prototypePrior( - const TMultivariatePriorPtr& prior) { + const TMultivariatePriorSPtr& prior) { m_PrototypePrior = prior; } } diff --git a/lib/model/CAnomalyDetectorModelConfig.cc b/lib/model/CAnomalyDetectorModelConfig.cc index 38128f5617..27aa6e17e9 100644 --- a/lib/model/CAnomalyDetectorModelConfig.cc +++ b/lib/model/CAnomalyDetectorModelConfig.cc @@ -10,6 +10,8 @@ #include #include +#include +#include #include #include diff --git a/lib/model/CCountingModelFactory.cc b/lib/model/CCountingModelFactory.cc index f1ce47f69f..3a48ccbeb9 100644 --- a/lib/model/CCountingModelFactory.cc +++ b/lib/model/CCountingModelFactory.cc @@ -10,11 +10,14 @@ #include #include +#include #include #include #include +#include + #include namespace ml { @@ -78,27 +81,26 @@ CCountingModelFactory::makeDataGatherer(const std::string& partitionFieldValue, CCountingModelFactory::TPriorPtr CCountingModelFactory::defaultPrior(model_t::EFeature /*feature*/, const SModelParams& /*params*/) const { - return std::make_shared(); + return boost::make_unique(); } -CCountingModelFactory::TMultivariatePriorPtr +CCountingModelFactory::TMultivariatePriorUPtr CCountingModelFactory::defaultMultivariatePrior(model_t::EFeature feature, const SModelParams& /*params*/) const { - return std::make_shared(model_t::dimension(feature)); + return boost::make_unique(model_t::dimension(feature)); } -CCountingModelFactory::TMultivariatePriorPtr +CCountingModelFactory::TMultivariatePriorUPtr CCountingModelFactory::defaultCorrelatePrior(model_t::EFeature /*feature*/, const SModelParams& /*params*/) const { - return std::make_shared(2); + return boost::make_unique(2); } const CSearchKey& CCountingModelFactory::searchKey() const { if (!m_SearchKeyCache) { - m_SearchKeyCache.reset( - CSearchKey(m_Identifier, function_t::function(m_Features), - m_UseNull, this->modelParams().s_ExcludeFrequent, "", - m_PersonFieldName, "", m_PartitionFieldName)); + m_SearchKeyCache.emplace(m_Identifier, function_t::function(m_Features), + m_UseNull, this->modelParams().s_ExcludeFrequent, + "", m_PersonFieldName, "", m_PartitionFieldName); } return *m_SearchKeyCache; } diff --git a/lib/model/CEventRateModel.cc b/lib/model/CEventRateModel.cc index 352bf4ef4d..ad679dce7e 100644 --- a/lib/model/CEventRateModel.cc +++ b/lib/model/CEventRateModel.cc @@ -59,9 +59,9 @@ const std::string PROBABILITY_PRIOR_TAG("b"); CEventRateModel::CEventRateModel(const SModelParams& params, const TDataGathererPtr& dataGatherer, - const TFeatureMathsModelPtrPrVec& newFeatureModels, - const TFeatureMultivariatePriorPtrPrVec& newFeatureCorrelateModelPriors, - const TFeatureCorrelationsPtrPrVec& featureCorrelatesModels, + const TFeatureMathsModelSPtrPrVec& newFeatureModels, + const TFeatureMultivariatePriorSPtrPrVec& newFeatureCorrelateModelPriors, + TFeatureCorrelationsPtrPrVec&& featureCorrelatesModels, const maths::CMultinomialConjugate& probabilityPrior, const TFeatureInfluenceCalculatorCPtrPrVecVec& influenceCalculators, const TInterimBucketCorrectorCPtr& interimBucketCorrector) @@ -69,7 +69,7 @@ CEventRateModel::CEventRateModel(const SModelParams& params, dataGatherer, newFeatureModels, newFeatureCorrelateModelPriors, - featureCorrelatesModels, + std::move(featureCorrelatesModels), influenceCalculators), m_CurrentBucketStats(CAnomalyDetectorModel::TIME_UNSET), m_ProbabilityPrior(probabilityPrior), @@ -78,9 +78,9 @@ CEventRateModel::CEventRateModel(const SModelParams& params, CEventRateModel::CEventRateModel(const SModelParams& params, const TDataGathererPtr& dataGatherer, - const TFeatureMathsModelPtrPrVec& newFeatureModels, - const TFeatureMultivariatePriorPtrPrVec& newFeatureCorrelateModelPriors, - const TFeatureCorrelationsPtrPrVec& featureCorrelatesModels, + const TFeatureMathsModelSPtrPrVec& newFeatureModels, + const TFeatureMultivariatePriorSPtrPrVec& newFeatureCorrelateModelPriors, + TFeatureCorrelationsPtrPrVec&& featureCorrelatesModels, const TFeatureInfluenceCalculatorCPtrPrVecVec& influenceCalculators, const TInterimBucketCorrectorCPtr& interimBucketCorrector, core::CStateRestoreTraverser& traverser) @@ -88,7 +88,7 @@ CEventRateModel::CEventRateModel(const SModelParams& params, dataGatherer, newFeatureModels, newFeatureCorrelateModelPriors, - featureCorrelatesModels, + std::move(featureCorrelatesModels), influenceCalculators), m_CurrentBucketStats(CAnomalyDetectorModel::TIME_UNSET), m_InterimBucketCorrector(interimBucketCorrector) { diff --git a/lib/model/CEventRateModelFactory.cc b/lib/model/CEventRateModelFactory.cc index a06898b9a4..cccf21f5ab 100644 --- a/lib/model/CEventRateModelFactory.cc +++ b/lib/model/CEventRateModelFactory.cc @@ -23,6 +23,8 @@ #include #include +#include + #include namespace ml { @@ -114,13 +116,13 @@ CEventRateModelFactory::defaultPrior(model_t::EFeature feature, // Categorical data all use the multinomial prior. The creation // of these priors is managed by defaultCategoricalPrior. if (model_t::isCategorical(feature)) { - return TPriorPtr(); + return nullptr; } // If the feature data only ever takes a single value we use a // special lightweight prior. if (model_t::isConstant(feature)) { - return std::make_shared(); + return boost::make_unique(); } // Gaussian mixture for modeling time-of-day and time-of-week. @@ -128,8 +130,6 @@ CEventRateModelFactory::defaultPrior(model_t::EFeature feature, return this->timeOfDayPrior(params); } - using TPriorPtrVec = std::vector; - // The data will be counts for the number of events in a specified // interval. As such we expect counts to be greater than or equal // to zero. We use a small non-zero offset, for the log-normal prior @@ -153,7 +153,7 @@ CEventRateModelFactory::defaultPrior(model_t::EFeature feature, maths::CPoissonMeanConjugate::nonInformativePrior(0.0, params.s_DecayRate); // Create the component priors. - TPriorPtrVec priors; + maths::COneOfNPrior::TPriorPtrVec priors; priors.reserve(params.s_MinimumModeFraction <= 0.5 ? 5u : 4u); priors.emplace_back(gammaPrior.clone()); priors.emplace_back(logNormalPrior.clone()); @@ -161,7 +161,7 @@ CEventRateModelFactory::defaultPrior(model_t::EFeature feature, priors.emplace_back(poissonPrior.clone()); if (params.s_MinimumModeFraction <= 0.5) { // Create the multimode prior. - TPriorPtrVec modePriors; + maths::COneOfNPrior::TPriorPtrVec modePriors; modePriors.reserve(3u); modePriors.emplace_back(gammaPrior.clone()); modePriors.emplace_back(logNormalPrior.clone()); @@ -176,44 +176,45 @@ CEventRateModelFactory::defaultPrior(model_t::EFeature feature, priors.emplace_back(multimodalPrior.clone()); } - return std::make_shared(priors, dataType, params.s_DecayRate); + return boost::make_unique(priors, dataType, params.s_DecayRate); } -CEventRateModelFactory::TMultivariatePriorPtr +CEventRateModelFactory::TMultivariatePriorUPtr CEventRateModelFactory::defaultMultivariatePrior(model_t::EFeature feature, const SModelParams& params) const { std::size_t dimension = model_t::dimension(feature); - TMultivariatePriorPtrVec priors; + TMultivariatePriorUPtrVec priors; priors.reserve(params.s_MinimumModeFraction <= 0.5 ? 2u : 1u); - TMultivariatePriorPtr multivariateNormal(this->multivariateNormalPrior(dimension, params)); - priors.push_back(multivariateNormal); + TMultivariatePriorUPtr normal{this->multivariateNormalPrior(dimension, params)}; + priors.push_back(std::move(normal)); if (params.s_MinimumModeFraction <= 0.5) { - priors.push_back(this->multivariateMultimodalPrior(dimension, params, *multivariateNormal)); + priors.push_back(this->multivariateMultimodalPrior(dimension, params, + *priors.back())); } return this->multivariateOneOfNPrior(dimension, params, priors); } -CEventRateModelFactory::TMultivariatePriorPtr +CEventRateModelFactory::TMultivariatePriorUPtr CEventRateModelFactory::defaultCorrelatePrior(model_t::EFeature /*feature*/, const SModelParams& params) const { - TMultivariatePriorPtrVec priors; + TMultivariatePriorUPtrVec priors; priors.reserve(params.s_MinimumModeFraction <= 0.5 ? 2u : 1u); - TMultivariatePriorPtr multivariateNormal = this->multivariateNormalPrior(2, params); - priors.push_back(multivariateNormal); + TMultivariatePriorUPtr normal{this->multivariateNormalPrior(2, params)}; + priors.push_back(std::move(normal)); if (params.s_MinimumModeFraction <= 0.5) { - priors.push_back(this->multivariateMultimodalPrior(2, params, *multivariateNormal)); + priors.push_back(this->multivariateMultimodalPrior(2, params, *priors.back())); } return this->multivariateOneOfNPrior(2, params, priors); } const CSearchKey& CEventRateModelFactory::searchKey() const { if (!m_SearchKeyCache) { - m_SearchKeyCache.reset(CSearchKey( - m_Identifier, function_t::function(m_Features), m_UseNull, - this->modelParams().s_ExcludeFrequent, m_ValueFieldName, - m_PersonFieldName, "", m_PartitionFieldName, m_InfluenceFieldNames)); + m_SearchKeyCache.emplace(m_Identifier, function_t::function(m_Features), + m_UseNull, this->modelParams().s_ExcludeFrequent, + m_ValueFieldName, m_PersonFieldName, "", + m_PartitionFieldName, m_InfluenceFieldNames); } return *m_SearchKeyCache; } diff --git a/lib/model/CEventRatePopulationModel.cc b/lib/model/CEventRatePopulationModel.cc index 5517803254..8a0124a54d 100644 --- a/lib/model/CEventRatePopulationModel.cc +++ b/lib/model/CEventRatePopulationModel.cc @@ -70,9 +70,9 @@ const std::string EMPTY_STRING(""); CEventRatePopulationModel::CEventRatePopulationModel( const SModelParams& params, const TDataGathererPtr& dataGatherer, - const TFeatureMathsModelPtrPrVec& newFeatureModels, - const TFeatureMultivariatePriorPtrPrVec& newFeatureCorrelateModelPriors, - const TFeatureCorrelationsPtrPrVec& featureCorrelatesModels, + const TFeatureMathsModelSPtrPrVec& newFeatureModels, + const TFeatureMultivariatePriorSPtrPrVec& newFeatureCorrelateModelPriors, + TFeatureCorrelationsPtrPrVec&& featureCorrelatesModels, const TFeatureInfluenceCalculatorCPtrPrVecVec& influenceCalculators, const TInterimBucketCorrectorCPtr& interimBucketCorrector) : CPopulationModel(params, dataGatherer, influenceCalculators), @@ -85,15 +85,16 @@ CEventRatePopulationModel::CEventRatePopulationModel( boost::numeric::bounds::highest(), params.s_DecayRate)), m_InterimBucketCorrector(interimBucketCorrector), m_Probabilities(0.05) { - this->initialize(newFeatureModels, newFeatureCorrelateModelPriors, featureCorrelatesModels); + this->initialize(newFeatureModels, newFeatureCorrelateModelPriors, + std::move(featureCorrelatesModels)); } CEventRatePopulationModel::CEventRatePopulationModel( const SModelParams& params, const TDataGathererPtr& dataGatherer, - const TFeatureMathsModelPtrPrVec& newFeatureModels, - const TFeatureMultivariatePriorPtrPrVec& newFeatureCorrelateModelPriors, - const TFeatureCorrelationsPtrPrVec& featureCorrelatesModels, + const TFeatureMathsModelSPtrPrVec& newFeatureModels, + const TFeatureMultivariatePriorSPtrPrVec& newFeatureCorrelateModelPriors, + TFeatureCorrelationsPtrPrVec&& featureCorrelatesModels, const TFeatureInfluenceCalculatorCPtrPrVecVec& influenceCalculators, const TInterimBucketCorrectorCPtr& interimBucketCorrector, core::CStateRestoreTraverser& traverser) @@ -101,15 +102,16 @@ CEventRatePopulationModel::CEventRatePopulationModel( m_CurrentBucketStats(dataGatherer->currentBucketStartTime() - dataGatherer->bucketLength()), m_InterimBucketCorrector(interimBucketCorrector), m_Probabilities(0.05) { - this->initialize(newFeatureModels, newFeatureCorrelateModelPriors, featureCorrelatesModels); + this->initialize(newFeatureModels, newFeatureCorrelateModelPriors, + std::move(featureCorrelatesModels)); traverser.traverseSubLevel( boost::bind(&CEventRatePopulationModel::acceptRestoreTraverser, this, _1)); } void CEventRatePopulationModel::initialize( - const TFeatureMathsModelPtrPrVec& newFeatureModels, - const TFeatureMultivariatePriorPtrPrVec& newFeatureCorrelateModelPriors, - const TFeatureCorrelationsPtrPrVec& featureCorrelatesModels) { + const TFeatureMathsModelSPtrPrVec& newFeatureModels, + const TFeatureMultivariatePriorSPtrPrVec& newFeatureCorrelateModelPriors, + TFeatureCorrelationsPtrPrVec&& featureCorrelatesModels) { m_FeatureModels.reserve(newFeatureModels.size()); for (const auto& model : newFeatureModels) { m_FeatureModels.emplace_back(model.first, model.second); @@ -125,7 +127,7 @@ void CEventRatePopulationModel::initialize( m_FeatureCorrelatesModels.emplace_back( featureCorrelatesModels[i].first, newFeatureCorrelateModelPriors[i].second, - featureCorrelatesModels[i].second); + std::move(featureCorrelatesModels[i].second)); } std::sort(m_FeatureCorrelatesModels.begin(), m_FeatureCorrelatesModels.end(), [](const SFeatureCorrelateModels& lhs, const SFeatureCorrelateModels& rhs) { @@ -365,7 +367,6 @@ void CEventRatePopulationModel::sample(core_t::TTime startTime, for (auto& featureData_ : featureData) { model_t::EFeature feature = featureData_.first; - std::size_t dimension = model_t::dimension(feature); TSizeSizePrFeatureDataPrVec& data = m_CurrentBucketStats.s_FeatureData[feature]; data.swap(featureData_.second); LOG_TRACE(<< model_t::print(feature) << ": " diff --git a/lib/model/CEventRatePopulationModelFactory.cc b/lib/model/CEventRatePopulationModelFactory.cc index 1d89c69fb0..4d719ea462 100644 --- a/lib/model/CEventRatePopulationModelFactory.cc +++ b/lib/model/CEventRatePopulationModelFactory.cc @@ -23,6 +23,8 @@ #include #include +#include + #include namespace ml { @@ -113,21 +115,19 @@ CEventRatePopulationModelFactory::defaultPrior(model_t::EFeature feature, // Categorical data all use the multinomial prior. The creation // of these priors is managed by defaultCategoricalPrior. if (model_t::isCategorical(feature)) { - return TPriorPtr(); + return nullptr; } // If the feature data only ever takes a single value we use a // special lightweight prior. if (model_t::isConstant(feature)) { - return std::make_shared(); + return boost::make_unique(); } if (model_t::isDiurnal(feature)) { return this->timeOfDayPrior(params); } - using TPriorPtrVec = std::vector; - // The feature data will be counts for the number of events in a // specified interval. As such we expect counts to be greater than // or equal to zero. We use a small non-zero offset, for the log- @@ -151,7 +151,7 @@ CEventRatePopulationModelFactory::defaultPrior(model_t::EFeature feature, maths::CPoissonMeanConjugate::nonInformativePrior(0.0, params.s_DecayRate); // Create the component priors. - TPriorPtrVec priors; + maths::COneOfNPrior::TPriorPtrVec priors; priors.reserve(params.s_MinimumModeFraction <= 0.5 ? 5u : 4u); priors.emplace_back(gammaPrior.clone()); priors.emplace_back(logNormalPrior.clone()); @@ -159,7 +159,7 @@ CEventRatePopulationModelFactory::defaultPrior(model_t::EFeature feature, priors.emplace_back(poissonPrior.clone()); if (params.s_MinimumModeFraction <= 0.5) { // Create the multimode prior. - TPriorPtrVec modePriors; + maths::COneOfNPrior::TPriorPtrVec modePriors; modePriors.reserve(3u); modePriors.emplace_back(gammaPrior.clone()); modePriors.emplace_back(logNormalPrior.clone()); @@ -174,45 +174,45 @@ CEventRatePopulationModelFactory::defaultPrior(model_t::EFeature feature, priors.emplace_back(multimodalPrior.clone()); } - return std::make_shared(priors, dataType, params.s_DecayRate); + return boost::make_unique(priors, dataType, params.s_DecayRate); } -CEventRatePopulationModelFactory::TMultivariatePriorPtr +CEventRatePopulationModelFactory::TMultivariatePriorUPtr CEventRatePopulationModelFactory::defaultMultivariatePrior(model_t::EFeature feature, const SModelParams& params) const { std::size_t dimension = model_t::dimension(feature); - TMultivariatePriorPtrVec priors; + TMultivariatePriorUPtrVec priors; priors.reserve(params.s_MinimumModeFraction <= 0.5 ? 2u : 1u); - TMultivariatePriorPtr multivariateNormal = - this->multivariateNormalPrior(dimension, params); - priors.push_back(multivariateNormal); + TMultivariatePriorUPtr normal{this->multivariateNormalPrior(dimension, params)}; + priors.push_back(std::move(normal)); if (params.s_MinimumModeFraction <= 0.5) { - priors.push_back(this->multivariateMultimodalPrior(dimension, params, *multivariateNormal)); + priors.push_back(this->multivariateMultimodalPrior(dimension, params, + *priors.back())); } return this->multivariateOneOfNPrior(dimension, params, priors); } -CEventRatePopulationModelFactory::TMultivariatePriorPtr +CEventRatePopulationModelFactory::TMultivariatePriorUPtr CEventRatePopulationModelFactory::defaultCorrelatePrior(model_t::EFeature /*feature*/, const SModelParams& params) const { - TMultivariatePriorPtrVec priors; + TMultivariatePriorUPtrVec priors; priors.reserve(params.s_MinimumModeFraction <= 0.5 ? 2u : 1u); - TMultivariatePriorPtr multivariateNormal = this->multivariateNormalPrior(2, params); - priors.push_back(multivariateNormal); + TMultivariatePriorUPtr normal{this->multivariateNormalPrior(2, params)}; + priors.push_back(std::move(normal)); if (params.s_MinimumModeFraction <= 0.5) { - priors.push_back(this->multivariateMultimodalPrior(2, params, *multivariateNormal)); + priors.push_back(this->multivariateMultimodalPrior(2, params, *priors.back())); } return this->multivariateOneOfNPrior(2, params, priors); } const CSearchKey& CEventRatePopulationModelFactory::searchKey() const { if (!m_SearchKeyCache) { - m_SearchKeyCache.reset(CSearchKey( - m_Identifier, function_t::function(m_Features), m_UseNull, - this->modelParams().s_ExcludeFrequent, m_ValueFieldName, m_AttributeFieldName, - m_PersonFieldName, m_PartitionFieldName, m_InfluenceFieldNames)); + m_SearchKeyCache.emplace(m_Identifier, function_t::function(m_Features), + m_UseNull, this->modelParams().s_ExcludeFrequent, + m_ValueFieldName, m_AttributeFieldName, m_PersonFieldName, + m_PartitionFieldName, m_InfluenceFieldNames); } return *m_SearchKeyCache; } diff --git a/lib/model/CForecastModelPersist.cc b/lib/model/CForecastModelPersist.cc index 5cdeeede50..1077d93f5b 100644 --- a/lib/model/CForecastModelPersist.cc +++ b/lib/model/CForecastModelPersist.cc @@ -118,7 +118,7 @@ bool CForecastModelPersist::CRestore::restoreOneModel(core::CStateRestoreTravers bool restoredFeature = false; bool restoredDataType = false; byFieldValue.clear(); - maths_t::EDataType dataType; + maths_t::EDataType dataType{}; do { const std::string& name = traverser.name(); diff --git a/lib/model/CIndividualModel.cc b/lib/model/CIndividualModel.cc index 1213c05534..55945b6ff8 100644 --- a/lib/model/CIndividualModel.cc +++ b/lib/model/CIndividualModel.cc @@ -72,9 +72,9 @@ const std::string MEMORY_ESTIMATOR_TAG("i"); CIndividualModel::CIndividualModel(const SModelParams& params, const TDataGathererPtr& dataGatherer, - const TFeatureMathsModelPtrPrVec& newFeatureModels, - const TFeatureMultivariatePriorPtrPrVec& newFeatureCorrelateModelPriors, - const TFeatureCorrelationsPtrPrVec& featureCorrelatesModels, + const TFeatureMathsModelSPtrPrVec& newFeatureModels, + const TFeatureMultivariatePriorSPtrPrVec& newFeatureCorrelateModelPriors, + TFeatureCorrelationsPtrPrVec&& featureCorrelatesModels, const TFeatureInfluenceCalculatorCPtrPrVecVec& influenceCalculators) : CAnomalyDetectorModel(params, dataGatherer, influenceCalculators) { m_FeatureModels.reserve(newFeatureModels.size()); @@ -92,7 +92,7 @@ CIndividualModel::CIndividualModel(const SModelParams& params, m_FeatureCorrelatesModels.emplace_back( featureCorrelatesModels[i].first, newFeatureCorrelateModelPriors[i].second, - featureCorrelatesModels[i].second); + std::move(featureCorrelatesModels[i].second)); } std::sort(m_FeatureCorrelatesModels.begin(), m_FeatureCorrelatesModels.end(), [](const SFeatureCorrelateModels& lhs, const SFeatureCorrelateModels& rhs) { diff --git a/lib/model/CMetricModel.cc b/lib/model/CMetricModel.cc index cf41cb12bb..f0212dc1bb 100644 --- a/lib/model/CMetricModel.cc +++ b/lib/model/CMetricModel.cc @@ -58,16 +58,16 @@ const std::string INDIVIDUAL_STATE_TAG("a"); CMetricModel::CMetricModel(const SModelParams& params, const TDataGathererPtr& dataGatherer, - const TFeatureMathsModelPtrPrVec& newFeatureModels, - const TFeatureMultivariatePriorPtrPrVec& newFeatureCorrelateModelPriors, - const TFeatureCorrelationsPtrPrVec& featureCorrelatesModels, + const TFeatureMathsModelSPtrPrVec& newFeatureModels, + const TFeatureMultivariatePriorSPtrPrVec& newFeatureCorrelateModelPriors, + TFeatureCorrelationsPtrPrVec&& featureCorrelatesModels, const TFeatureInfluenceCalculatorCPtrPrVecVec& influenceCalculators, const TInterimBucketCorrectorCPtr& interimBucketCorrector) : CIndividualModel(params, dataGatherer, newFeatureModels, newFeatureCorrelateModelPriors, - featureCorrelatesModels, + std::move(featureCorrelatesModels), influenceCalculators), m_CurrentBucketStats(CAnomalyDetectorModel::TIME_UNSET), m_InterimBucketCorrector(interimBucketCorrector) { @@ -75,9 +75,9 @@ CMetricModel::CMetricModel(const SModelParams& params, CMetricModel::CMetricModel(const SModelParams& params, const TDataGathererPtr& dataGatherer, - const TFeatureMathsModelPtrPrVec& newFeatureModels, - const TFeatureMultivariatePriorPtrPrVec& newFeatureCorrelateModelPriors, - const TFeatureCorrelationsPtrPrVec& featureCorrelatesModels, + const TFeatureMathsModelSPtrPrVec& newFeatureModels, + const TFeatureMultivariatePriorSPtrPrVec& newFeatureCorrelateModelPriors, + TFeatureCorrelationsPtrPrVec&& featureCorrelatesModels, const TFeatureInfluenceCalculatorCPtrPrVecVec& influenceCalculators, const TInterimBucketCorrectorCPtr& interimBucketCorrector, core::CStateRestoreTraverser& traverser) @@ -85,7 +85,7 @@ CMetricModel::CMetricModel(const SModelParams& params, dataGatherer, newFeatureModels, newFeatureCorrelateModelPriors, - featureCorrelatesModels, + std::move(featureCorrelatesModels), influenceCalculators), m_CurrentBucketStats(CAnomalyDetectorModel::TIME_UNSET), m_InterimBucketCorrector(interimBucketCorrector) { diff --git a/lib/model/CMetricModelFactory.cc b/lib/model/CMetricModelFactory.cc index a3d264695c..e608babad5 100644 --- a/lib/model/CMetricModelFactory.cc +++ b/lib/model/CMetricModelFactory.cc @@ -21,6 +21,8 @@ #include #include +#include + #include namespace ml { @@ -111,17 +113,15 @@ CMetricModelFactory::defaultPrior(model_t::EFeature feature, const SModelParams& // Categorical data all use the multinomial prior. The creation // of these priors is managed by defaultCategoricalPrior. if (model_t::isCategorical(feature)) { - return TPriorPtr(); + return nullptr; } // If the feature data only ever takes a single value we use a // special lightweight prior. if (model_t::isConstant(feature)) { - return std::make_shared(); + return boost::make_unique(); } - using TPriorPtrVec = std::vector; - // The data will be arbitrary metric values. Metrics with negative values // will be handled by adjusting offsets in the gamma and log-normal priors // on the fly. We start off with a small non-zero offset for the log-normal @@ -144,14 +144,14 @@ CMetricModelFactory::defaultPrior(model_t::EFeature feature, const SModelParams& maths::CNormalMeanPrecConjugate::nonInformativePrior(dataType, params.s_DecayRate); // Create the component priors. - TPriorPtrVec priors; + maths::COneOfNPrior::TPriorPtrVec priors; priors.reserve(params.s_MinimumModeFraction <= 0.5 ? 4u : 3u); priors.emplace_back(gammaPrior.clone()); priors.emplace_back(logNormalPrior.clone()); priors.emplace_back(normalPrior.clone()); if (params.s_MinimumModeFraction <= 0.5) { // Create the multimode prior. - TPriorPtrVec modePriors; + maths::COneOfNPrior::TPriorPtrVec modePriors; modePriors.reserve(3u); modePriors.emplace_back(gammaPrior.clone()); modePriors.emplace_back(logNormalPrior.clone()); @@ -166,10 +166,10 @@ CMetricModelFactory::defaultPrior(model_t::EFeature feature, const SModelParams& priors.emplace_back(multimodalPrior.clone()); } - return std::make_shared(priors, dataType, params.s_DecayRate); + return boost::make_unique(priors, dataType, params.s_DecayRate); } -CMetricModelFactory::TMultivariatePriorPtr +CMetricModelFactory::TMultivariatePriorUPtr CMetricModelFactory::defaultMultivariatePrior(model_t::EFeature feature, const SModelParams& params) const { std::size_t dimension = model_t::dimension(feature); @@ -179,37 +179,37 @@ CMetricModelFactory::defaultMultivariatePrior(model_t::EFeature feature, return this->latLongPrior(params); } - TMultivariatePriorPtrVec priors; + TMultivariatePriorUPtrVec priors; priors.reserve(params.s_MinimumModeFraction <= 0.5 ? 2u : 1u); - TMultivariatePriorPtr multivariateNormal = - this->multivariateNormalPrior(dimension, params); - priors.push_back(multivariateNormal); + TMultivariatePriorUPtr normal{this->multivariateNormalPrior(dimension, params)}; + priors.push_back(std::move(normal)); if (params.s_MinimumModeFraction <= 0.5) { - priors.push_back(this->multivariateMultimodalPrior(dimension, params, *multivariateNormal)); + priors.push_back(this->multivariateMultimodalPrior(dimension, params, + *priors.back())); } return this->multivariateOneOfNPrior(dimension, params, priors); } -CMetricModelFactory::TMultivariatePriorPtr +CMetricModelFactory::TMultivariatePriorUPtr CMetricModelFactory::defaultCorrelatePrior(model_t::EFeature /*feature*/, const SModelParams& params) const { - TMultivariatePriorPtrVec priors; + TMultivariatePriorUPtrVec priors; priors.reserve(params.s_MinimumModeFraction <= 0.5 ? 2u : 1u); - TMultivariatePriorPtr multivariateNormal = this->multivariateNormalPrior(2, params); - priors.push_back(multivariateNormal); + TMultivariatePriorUPtr normal{this->multivariateNormalPrior(2, params)}; + priors.push_back(std::move(normal)); if (params.s_MinimumModeFraction <= 0.5) { - priors.push_back(this->multivariateMultimodalPrior(2, params, *multivariateNormal)); + priors.push_back(this->multivariateMultimodalPrior(2, params, *priors.back())); } return this->multivariateOneOfNPrior(2, params, priors); } const CSearchKey& CMetricModelFactory::searchKey() const { if (!m_SearchKeyCache) { - m_SearchKeyCache.reset(CSearchKey( - m_Identifier, function_t::function(m_Features), m_UseNull, - this->modelParams().s_ExcludeFrequent, m_ValueFieldName, - m_PersonFieldName, "", m_PartitionFieldName, m_InfluenceFieldNames)); + m_SearchKeyCache.emplace(m_Identifier, function_t::function(m_Features), + m_UseNull, this->modelParams().s_ExcludeFrequent, + m_ValueFieldName, m_PersonFieldName, "", + m_PartitionFieldName, m_InfluenceFieldNames); } return *m_SearchKeyCache; } diff --git a/lib/model/CMetricPopulationModel.cc b/lib/model/CMetricPopulationModel.cc index 701bb39623..269b2cdfe5 100644 --- a/lib/model/CMetricPopulationModel.cc +++ b/lib/model/CMetricPopulationModel.cc @@ -76,24 +76,25 @@ const std::string MEMORY_ESTIMATOR_TAG("d"); CMetricPopulationModel::CMetricPopulationModel( const SModelParams& params, const TDataGathererPtr& dataGatherer, - const TFeatureMathsModelPtrPrVec& newFeatureModels, - const TFeatureMultivariatePriorPtrPrVec& newFeatureCorrelateModelPriors, - const TFeatureCorrelationsPtrPrVec& featureCorrelatesModels, + const TFeatureMathsModelSPtrPrVec& newFeatureModels, + const TFeatureMultivariatePriorSPtrPrVec& newFeatureCorrelateModelPriors, + TFeatureCorrelationsPtrPrVec&& featureCorrelatesModels, const TFeatureInfluenceCalculatorCPtrPrVecVec& influenceCalculators, const TInterimBucketCorrectorCPtr& interimBucketCorrector) : CPopulationModel(params, dataGatherer, influenceCalculators), m_CurrentBucketStats(dataGatherer->currentBucketStartTime() - dataGatherer->bucketLength()), m_InterimBucketCorrector(interimBucketCorrector), m_Probabilities(0.05) { - this->initialize(newFeatureModels, newFeatureCorrelateModelPriors, featureCorrelatesModels); + this->initialize(newFeatureModels, newFeatureCorrelateModelPriors, + std::move(featureCorrelatesModels)); } CMetricPopulationModel::CMetricPopulationModel( const SModelParams& params, const TDataGathererPtr& dataGatherer, - const TFeatureMathsModelPtrPrVec& newFeatureModels, - const TFeatureMultivariatePriorPtrPrVec& newFeatureCorrelateModelPriors, - const TFeatureCorrelationsPtrPrVec& featureCorrelatesModels, + const TFeatureMathsModelSPtrPrVec& newFeatureModels, + const TFeatureMultivariatePriorSPtrPrVec& newFeatureCorrelateModelPriors, + TFeatureCorrelationsPtrPrVec&& featureCorrelatesModels, const TFeatureInfluenceCalculatorCPtrPrVecVec& influenceCalculators, const TInterimBucketCorrectorCPtr& interimBucketCorrector, core::CStateRestoreTraverser& traverser) @@ -101,14 +102,15 @@ CMetricPopulationModel::CMetricPopulationModel( m_CurrentBucketStats(dataGatherer->currentBucketStartTime() - dataGatherer->bucketLength()), m_InterimBucketCorrector(interimBucketCorrector), m_Probabilities(0.05) { - this->initialize(newFeatureModels, newFeatureCorrelateModelPriors, featureCorrelatesModels); + this->initialize(newFeatureModels, newFeatureCorrelateModelPriors, + std::move(featureCorrelatesModels)); traverser.traverseSubLevel( boost::bind(&CMetricPopulationModel::acceptRestoreTraverser, this, _1)); } -void CMetricPopulationModel::initialize(const TFeatureMathsModelPtrPrVec& newFeatureModels, - const TFeatureMultivariatePriorPtrPrVec& newFeatureCorrelateModelPriors, - const TFeatureCorrelationsPtrPrVec& featureCorrelatesModels) { +void CMetricPopulationModel::initialize(const TFeatureMathsModelSPtrPrVec& newFeatureModels, + const TFeatureMultivariatePriorSPtrPrVec& newFeatureCorrelateModelPriors, + TFeatureCorrelationsPtrPrVec&& featureCorrelatesModels) { m_FeatureModels.reserve(newFeatureModels.size()); for (const auto& model : newFeatureModels) { m_FeatureModels.emplace_back(model.first, model.second); @@ -124,7 +126,7 @@ void CMetricPopulationModel::initialize(const TFeatureMathsModelPtrPrVec& newFea m_FeatureCorrelatesModels.emplace_back( featureCorrelatesModels[i].first, newFeatureCorrelateModelPriors[i].second, - featureCorrelatesModels[i].second); + std::move(featureCorrelatesModels[i].second)); } std::sort(m_FeatureCorrelatesModels.begin(), m_FeatureCorrelatesModels.end(), [](const SFeatureCorrelateModels& lhs, const SFeatureCorrelateModels& rhs) { diff --git a/lib/model/CMetricPopulationModelFactory.cc b/lib/model/CMetricPopulationModelFactory.cc index c360d87eae..28e49a5058 100644 --- a/lib/model/CMetricPopulationModelFactory.cc +++ b/lib/model/CMetricPopulationModelFactory.cc @@ -21,6 +21,8 @@ #include #include +#include + #include namespace ml { @@ -111,17 +113,15 @@ CMetricPopulationModelFactory::defaultPrior(model_t::EFeature feature, // Categorical data all use the multinomial prior. The creation // of these priors is managed by defaultCategoricalPrior. if (model_t::isCategorical(feature)) { - return TPriorPtr(); + return nullptr; } // If the feature data only ever takes a single value we use a // special lightweight prior. if (model_t::isConstant(feature)) { - return std::make_shared(); + return boost::make_unique(); } - using TPriorPtrVec = std::vector; - // The data will be arbitrary metric values. Metrics with negative values // will be handled by adjusting offsets in the gamma and log-normal priors // on the fly. We start off with a small non-zero offset for the log-normal @@ -144,14 +144,14 @@ CMetricPopulationModelFactory::defaultPrior(model_t::EFeature feature, maths::CNormalMeanPrecConjugate::nonInformativePrior(dataType, params.s_DecayRate); // Create the component priors. - TPriorPtrVec priors; + maths::COneOfNPrior::TPriorPtrVec priors; priors.reserve(params.s_MinimumModeFraction <= 0.5 ? 4u : 3u); priors.emplace_back(gammaPrior.clone()); priors.emplace_back(logNormalPrior.clone()); priors.emplace_back(normalPrior.clone()); if (params.s_MinimumModeFraction <= 0.5) { // Create the multimode prior. - TPriorPtrVec modePriors; + maths::COneOfNPrior::TPriorPtrVec modePriors; modePriors.reserve(3u); modePriors.emplace_back(gammaPrior.clone()); modePriors.emplace_back(logNormalPrior.clone()); @@ -166,10 +166,10 @@ CMetricPopulationModelFactory::defaultPrior(model_t::EFeature feature, priors.emplace_back(multimodalPrior.clone()); } - return std::make_shared(priors, dataType, params.s_DecayRate); + return boost::make_unique(priors, dataType, params.s_DecayRate); } -CMetricPopulationModelFactory::TMultivariatePriorPtr +CMetricPopulationModelFactory::TMultivariatePriorUPtr CMetricPopulationModelFactory::defaultMultivariatePrior(model_t::EFeature feature, const SModelParams& params) const { std::size_t dimension = model_t::dimension(feature); @@ -179,37 +179,37 @@ CMetricPopulationModelFactory::defaultMultivariatePrior(model_t::EFeature featur return this->latLongPrior(params); } - TMultivariatePriorPtrVec priors; + TMultivariatePriorUPtrVec priors; priors.reserve(params.s_MinimumModeFraction <= 0.5 ? 2u : 1u); - TMultivariatePriorPtr multivariateNormal = - this->multivariateNormalPrior(dimension, params); - priors.push_back(multivariateNormal); + TMultivariatePriorUPtr normal{this->multivariateNormalPrior(dimension, params)}; + priors.push_back(std::move(normal)); if (params.s_MinimumModeFraction <= 0.5) { - priors.push_back(this->multivariateMultimodalPrior(dimension, params, *multivariateNormal)); + priors.push_back(this->multivariateMultimodalPrior(dimension, params, + *priors.back())); } return this->multivariateOneOfNPrior(dimension, params, priors); } -CMetricPopulationModelFactory::TMultivariatePriorPtr +CMetricPopulationModelFactory::TMultivariatePriorUPtr CMetricPopulationModelFactory::defaultCorrelatePrior(model_t::EFeature /*feature*/, const SModelParams& params) const { - TMultivariatePriorPtrVec priors; + TMultivariatePriorUPtrVec priors; priors.reserve(params.s_MinimumModeFraction <= 0.5 ? 2u : 1u); - TMultivariatePriorPtr multivariateNormal = this->multivariateNormalPrior(2, params); - priors.push_back(multivariateNormal); + TMultivariatePriorUPtr normal{this->multivariateNormalPrior(2, params)}; + priors.push_back(std::move(normal)); if (params.s_MinimumModeFraction <= 0.5) { - priors.push_back(this->multivariateMultimodalPrior(2, params, *multivariateNormal)); + priors.push_back(this->multivariateMultimodalPrior(2, params, *priors.back())); } return this->multivariateOneOfNPrior(2, params, priors); } const CSearchKey& CMetricPopulationModelFactory::searchKey() const { if (!m_SearchKeyCache) { - m_SearchKeyCache.reset(CSearchKey( - m_Identifier, function_t::function(m_Features), m_UseNull, - this->modelParams().s_ExcludeFrequent, m_ValueFieldName, m_AttributeFieldName, - m_PersonFieldName, m_PartitionFieldName, m_InfluenceFieldNames)); + m_SearchKeyCache.emplace(m_Identifier, function_t::function(m_Features), + m_UseNull, this->modelParams().s_ExcludeFrequent, + m_ValueFieldName, m_AttributeFieldName, m_PersonFieldName, + m_PartitionFieldName, m_InfluenceFieldNames); } return *m_SearchKeyCache; } diff --git a/lib/model/CModelFactory.cc b/lib/model/CModelFactory.cc index aeefab4bfa..fcf5cee33a 100644 --- a/lib/model/CModelFactory.cc +++ b/lib/model/CModelFactory.cc @@ -30,6 +30,7 @@ #include #include +#include namespace ml { namespace model { @@ -101,16 +102,15 @@ CModelFactory::defaultFeatureModel(model_t::EFeature feature, modelAnomalies && !model_t::isConstant(feature)); } - TMultivariatePriorPtr prior{this->defaultMultivariatePrior(feature)}; + TMultivariatePriorUPtr prior{this->defaultMultivariatePrior(feature)}; return std::make_shared( params, *trend, *prior, controlDecayRate ? &controllers : nullptr, modelAnomalies && !model_t::isConstant(feature)); } -const CModelFactory::TFeatureMultivariatePriorPtrPrVec& +const CModelFactory::TFeatureMultivariatePriorSPtrPrVec& CModelFactory::defaultCorrelatePriors(const TFeatureVec& features) const { - auto result = m_CorrelatePriorCache.insert( - {features, TFeatureMultivariatePriorPtrPrVec()}); + auto result = m_CorrelatePriorCache.emplace(features, TFeatureMultivariatePriorSPtrPrVec{}); if (result.second) { result.first->second.reserve(features.size()); for (auto feature : features) { @@ -123,33 +123,30 @@ CModelFactory::defaultCorrelatePriors(const TFeatureVec& features) const { return result.first->second; } -const CModelFactory::TFeatureCorrelationsPtrPrVec& +CModelFactory::TFeatureCorrelationsPtrPrVec CModelFactory::defaultCorrelates(const TFeatureVec& features) const { - auto result = m_CorrelationsCache.insert({features, TFeatureCorrelationsPtrPrVec()}); - if (result.second) { - result.first->second.reserve(features.size()); - for (auto feature : features) { - if (!model_t::isCategorical(feature) && model_t::dimension(feature) == 1) { - result.first->second.emplace_back( - feature, TCorrelationsPtr(new maths::CTimeSeriesCorrelations( - m_ModelParams.s_MinimumSignificantCorrelation, - m_ModelParams.s_DecayRate))); - } + TFeatureCorrelationsPtrPrVec result; + result.reserve(features.size()); + for (auto feature : features) { + if (!model_t::isCategorical(feature) && model_t::dimension(feature) == 1) { + result.emplace_back(feature, boost::make_unique( + m_ModelParams.s_MinimumSignificantCorrelation, + m_ModelParams.s_DecayRate)); } } - return result.first->second; + return result; } CModelFactory::TPriorPtr CModelFactory::defaultPrior(model_t::EFeature feature) const { return this->defaultPrior(feature, m_ModelParams); } -CModelFactory::TMultivariatePriorPtr +CModelFactory::TMultivariatePriorUPtr CModelFactory::defaultMultivariatePrior(model_t::EFeature feature) const { return this->defaultMultivariatePrior(feature, m_ModelParams); } -CModelFactory::TMultivariatePriorPtr +CModelFactory::TMultivariatePriorUPtr CModelFactory::defaultCorrelatePrior(model_t::EFeature feature) const { return this->defaultCorrelatePrior(feature, m_ModelParams); } @@ -297,13 +294,13 @@ CModelFactory::TInterimBucketCorrectorPtr CModelFactory::interimBucketCorrector( return result; } -CModelFactory::TMultivariatePriorPtr +CModelFactory::TMultivariatePriorUPtr CModelFactory::multivariateNormalPrior(std::size_t dimension, const SModelParams& params) const { return maths::CMultivariateNormalConjugateFactory::nonInformative( dimension, this->dataType(), params.s_DecayRate); } -CModelFactory::TMultivariatePriorPtr +CModelFactory::TMultivariatePriorUPtr CModelFactory::multivariateMultimodalPrior(std::size_t dimension, const SModelParams& params, const maths::CMultivariatePrior& modePrior) const { @@ -313,17 +310,15 @@ CModelFactory::multivariateMultimodalPrior(std::size_t dimension, params.s_MinimumModeCount, params.minimumCategoryCount(), modePrior); } -CModelFactory::TMultivariatePriorPtr +CModelFactory::TMultivariatePriorUPtr CModelFactory::multivariateOneOfNPrior(std::size_t dimension, const SModelParams& params, - const TMultivariatePriorPtrVec& models) const { + const TMultivariatePriorUPtrVec& models) const { return maths::CMultivariateOneOfNPriorFactory::nonInformative( dimension, this->dataType(), params.s_DecayRate, models); } CModelFactory::TPriorPtr CModelFactory::timeOfDayPrior(const SModelParams& params) const { - using TPriorPtrVec = std::vector; - maths_t::EDataType dataType = this->dataType(); maths::CNormalMeanPrecConjugate normalPrior = maths::CNormalMeanPrecConjugate::nonInformativePrior(dataType, params.s_DecayRate); @@ -331,7 +326,7 @@ CModelFactory::TPriorPtr CModelFactory::timeOfDayPrior(const SModelParams& param // Create a multimodal prior with purely normal distributions // - don't bother with long-tail distributions - TPriorPtrVec modePriors; + maths::COneOfNPrior::TPriorPtrVec modePriors; modePriors.reserve(1u); modePriors.emplace_back(normalPrior.clone()); maths::COneOfNPrior modePrior(modePriors, dataType, params.s_DecayRate); @@ -342,14 +337,14 @@ CModelFactory::TPriorPtr CModelFactory::timeOfDayPrior(const SModelParams& param 4, // minimumClusterCount CAnomalyDetectorModelConfig::DEFAULT_CATEGORY_DELETE_FRACTION); - return std::make_shared(dataType, clusterer, modePrior, - params.s_DecayRate); + return boost::make_unique(dataType, clusterer, modePrior, + params.s_DecayRate); } -CModelFactory::TMultivariatePriorPtr +CModelFactory::TMultivariatePriorUPtr CModelFactory::latLongPrior(const SModelParams& params) const { maths_t::EDataType dataType = this->dataType(); - TMultivariatePriorPtr modePrior = maths::CMultivariateNormalConjugateFactory::nonInformative( + TMultivariatePriorUPtr modePrior = maths::CMultivariateNormalConjugateFactory::nonInformative( 2, dataType, params.s_DecayRate); return maths::CMultivariateMultimodalPriorFactory::nonInformative( 2, // dimension diff --git a/lib/model/CResourceMonitor.cc b/lib/model/CResourceMonitor.cc index 6e1fd65a25..3f2dc8c308 100644 --- a/lib/model/CResourceMonitor.cc +++ b/lib/model/CResourceMonitor.cc @@ -42,7 +42,7 @@ void CResourceMonitor::memoryUsageReporter(const TMemoryUsageReporterFunc& repor } void CResourceMonitor::registerComponent(CAnomalyDetector& detector) { - LOG_TRACE(<< "Registering component: " << detector.model()); + LOG_TRACE(<< "Registering component: " << detector.model().get()); m_Models.insert({detector.model().get(), std::size_t(0)}); } @@ -50,11 +50,11 @@ void CResourceMonitor::unRegisterComponent(CAnomalyDetector& detector) { auto iter = m_Models.find(detector.model().get()); if (iter == m_Models.end()) { LOG_ERROR(<< "Inconsistency - component has not been registered: " - << detector.model()); + << detector.model().get()); return; } - LOG_TRACE(<< "Unregistering component: " << detector.model()); + LOG_TRACE(<< "Unregistering component: " << detector.model().get()); m_Models.erase(iter); } diff --git a/lib/model/unittest/CModelDetailsViewTest.cc b/lib/model/unittest/CModelDetailsViewTest.cc index 1714acc287..c2f5080948 100644 --- a/lib/model/unittest/CModelDetailsViewTest.cc +++ b/lib/model/unittest/CModelDetailsViewTest.cc @@ -67,11 +67,12 @@ void CModelDetailsViewTest::testModelPlot() { bucketLength, 1.0, 0.001, 0.2, 6 * core::constants::HOUR, 24 * core::constants::HOUR}; maths::CUnivariateTimeSeriesModel timeSeriesModel{timeSeriesModelParams, 0, trend, prior}; - model->mockTimeSeriesModels( - {model::CMockModel::TMathsModelPtr(timeSeriesModel.clone(0)), - model::CMockModel::TMathsModelPtr(timeSeriesModel.clone(1)), - model::CMockModel::TMathsModelPtr(timeSeriesModel.clone(2)), - model::CMockModel::TMathsModelPtr(timeSeriesModel.clone(3))}); + model::CMockModel::TMathsModelUPtrVec models; + models.emplace_back(timeSeriesModel.clone(0)); + models.emplace_back(timeSeriesModel.clone(1)); + models.emplace_back(timeSeriesModel.clone(2)); + models.emplace_back(timeSeriesModel.clone(3)); + model->mockTimeSeriesModels(std::move(models)); }; LOG_DEBUG(<< "Individual sum"); diff --git a/lib/model/unittest/CResourceLimitTest.cc b/lib/model/unittest/CResourceLimitTest.cc index d549808cfd..a7aeb75e0b 100644 --- a/lib/model/unittest/CResourceLimitTest.cc +++ b/lib/model/unittest/CResourceLimitTest.cc @@ -240,14 +240,14 @@ class CMockEventRateModel : public ml::model::CEventRateModel { public: CMockEventRateModel(const SModelParams& params, const TDataGathererPtr& dataGatherer, - const TFeatureMathsModelPtrPrVec& newFeatureModels, + const TFeatureMathsModelSPtrPrVec& newFeatureModels, const maths::CMultinomialConjugate& personProbabilityPrior, const TFeatureInfluenceCalculatorCPtrPrVecVec& influenceCalculators, CResourceMonitor& resourceMonitor) : CEventRateModel(params, dataGatherer, newFeatureModels, - TFeatureMultivariatePriorPtrPrVec(), + TFeatureMultivariatePriorSPtrPrVec(), TFeatureCorrelationsPtrPrVec(), personProbabilityPrior, influenceCalculators, @@ -284,13 +284,13 @@ class CMockMetricModel : public ml::model::CMetricModel { public: CMockMetricModel(const SModelParams& params, const TDataGathererPtr& dataGatherer, - const TFeatureMathsModelPtrPrVec& newFeatureModels, + const TFeatureMathsModelSPtrPrVec& newFeatureModels, const TFeatureInfluenceCalculatorCPtrPrVecVec& influenceCalculators, CResourceMonitor& resourceMonitor) : CMetricModel(params, dataGatherer, newFeatureModels, - TFeatureMultivariatePriorPtrPrVec(), + TFeatureMultivariatePriorSPtrPrVec(), TFeatureCorrelationsPtrPrVec(), influenceCalculators, std::make_shared(params.s_BucketLength)), diff --git a/lib/model/unittest/Mocks.cc b/lib/model/unittest/Mocks.cc index 345c2dd06c..7fddaadb53 100644 --- a/lib/model/unittest/Mocks.cc +++ b/lib/model/unittest/Mocks.cc @@ -190,8 +190,8 @@ void CMockModel::mockAddBucketBaselineMean(model_t::EFeature feature, m_BucketBaselineMeans[{feature, core::make_triple(pid, cid, time)}] = value; } -void CMockModel::mockTimeSeriesModels(const TMathsModelPtrVec& models) { - m_Models = models; +void CMockModel::mockTimeSeriesModels(TMathsModelUPtrVec&& models) { + m_Models = std::move(models); } CMemoryUsageEstimator* CMockModel::memoryUsageEstimator() const { diff --git a/lib/model/unittest/Mocks.h b/lib/model/unittest/Mocks.h index 74064d9833..2801c97573 100644 --- a/lib/model/unittest/Mocks.h +++ b/lib/model/unittest/Mocks.h @@ -118,7 +118,7 @@ class CMockModel : public CAnomalyDetectorModel { core_t::TTime time, const TDouble1Vec& value); - void mockTimeSeriesModels(const TMathsModelPtrVec& model); + void mockTimeSeriesModels(TMathsModelUPtrVec&& model); private: using TDouble1Vec = CAnomalyDetectorModel::TDouble1Vec; @@ -141,7 +141,7 @@ class CMockModel : public CAnomalyDetectorModel { bool m_IsPopulation; TFeatureSizeSizeTimeTriplePrDouble1VecUMap m_BucketValues; TFeatureSizeSizeTimeTriplePrDouble1VecUMap m_BucketBaselineMeans; - TMathsModelPtrVec m_Models; + TMathsModelUPtrVec m_Models; model::CInterimBucketCorrector m_InterimBucketCorrector; };