From 72f2f313b91fa181fe293bff9820fbeddd21f3fa Mon Sep 17 00:00:00 2001 From: HPDell Date: Tue, 22 Jul 2025 14:39:11 +0100 Subject: [PATCH 1/5] edit: spatial weight use smart pointer --- .../gwmodelpp/spatialweight/BandwidthWeight.h | 4 +- include/gwmodelpp/spatialweight/CRSDistance.h | 4 +- .../gwmodelpp/spatialweight/CRSSTDistance.h | 4 +- .../gwmodelpp/spatialweight/DMatDistance.h | 4 +- include/gwmodelpp/spatialweight/Distance.h | 2 +- .../spatialweight/MinkwoskiDistance.h | 4 +- .../gwmodelpp/spatialweight/OneDimDistance.h | 4 +- .../gwmodelpp/spatialweight/SpatialWeight.h | 158 +++++++++++------- include/gwmodelpp/spatialweight/Weight.h | 2 +- src/gwmodelpp/spatialweight/SpatialWeight.cpp | 23 +-- 10 files changed, 116 insertions(+), 93 deletions(-) diff --git a/include/gwmodelpp/spatialweight/BandwidthWeight.h b/include/gwmodelpp/spatialweight/BandwidthWeight.h index e15828c7..084ed530 100644 --- a/include/gwmodelpp/spatialweight/BandwidthWeight.h +++ b/include/gwmodelpp/spatialweight/BandwidthWeight.h @@ -172,9 +172,9 @@ class BandwidthWeight : public Weight mKernel = bandwidthWeight->kernel(); } - virtual Weight * clone() const override + virtual std::unique_ptr clone() const override { - return new BandwidthWeight(*this); + return std::make_unique(*this); } public: diff --git a/include/gwmodelpp/spatialweight/CRSDistance.h b/include/gwmodelpp/spatialweight/CRSDistance.h index 461f0ead..f169bbff 100644 --- a/include/gwmodelpp/spatialweight/CRSDistance.h +++ b/include/gwmodelpp/spatialweight/CRSDistance.h @@ -149,9 +149,9 @@ class CRSDistance : public Distance { } - virtual Distance * clone() const override + virtual std::unique_ptr clone() const override { - return new CRSDistance(*this); + return std::make_unique(*this); } DistanceType type() override { return DistanceType::CRSDistance; } diff --git a/include/gwmodelpp/spatialweight/CRSSTDistance.h b/include/gwmodelpp/spatialweight/CRSSTDistance.h index 3717d150..07cc20d0 100644 --- a/include/gwmodelpp/spatialweight/CRSSTDistance.h +++ b/include/gwmodelpp/spatialweight/CRSSTDistance.h @@ -75,9 +75,9 @@ class CRSSTDistance : public Distance */ CRSSTDistance(const CRSSTDistance& distance); - Distance * clone() const override + std::unique_ptr clone() const override { - return new CRSSTDistance(*this); + return std::make_unique(*this); } DistanceType type() override { return DistanceType::CRSSTDistance; } diff --git a/include/gwmodelpp/spatialweight/DMatDistance.h b/include/gwmodelpp/spatialweight/DMatDistance.h index 6b973704..c7af280d 100644 --- a/include/gwmodelpp/spatialweight/DMatDistance.h +++ b/include/gwmodelpp/spatialweight/DMatDistance.h @@ -44,9 +44,9 @@ class DMatDistance : public Distance */ DMatDistance(const DMatDistance& distance); - virtual Distance * clone() const override + virtual std::unique_ptr clone() const override { - return new DMatDistance(*this); + return std::make_unique(*this); } DistanceType type() override { return DistanceType::DMatDistance; } diff --git a/include/gwmodelpp/spatialweight/Distance.h b/include/gwmodelpp/spatialweight/Distance.h index 31202fc1..3cbcc14c 100644 --- a/include/gwmodelpp/spatialweight/Distance.h +++ b/include/gwmodelpp/spatialweight/Distance.h @@ -74,7 +74,7 @@ class Distance * * @return Distance* \~english Newly created pointer \~chinese 重新创建的对象指针 */ - virtual Distance* clone() const = 0; + virtual std::unique_ptr clone() const = 0; /** * @brief \~english Return the type of this object. \~chinese 返回该对象的类型。 diff --git a/include/gwmodelpp/spatialweight/MinkwoskiDistance.h b/include/gwmodelpp/spatialweight/MinkwoskiDistance.h index 23954768..a9c12407 100644 --- a/include/gwmodelpp/spatialweight/MinkwoskiDistance.h +++ b/include/gwmodelpp/spatialweight/MinkwoskiDistance.h @@ -70,9 +70,9 @@ class MinkwoskiDistance : public CRSDistance */ MinkwoskiDistance(const MinkwoskiDistance& distance); - virtual Distance * clone() const override + virtual std::unique_ptr clone() const override { - return new MinkwoskiDistance(*this); + return std::make_unique(*this); } DistanceType type() override { return DistanceType::MinkwoskiDistance; } diff --git a/include/gwmodelpp/spatialweight/OneDimDistance.h b/include/gwmodelpp/spatialweight/OneDimDistance.h index 1b4bcc7d..3d1d4e01 100644 --- a/include/gwmodelpp/spatialweight/OneDimDistance.h +++ b/include/gwmodelpp/spatialweight/OneDimDistance.h @@ -70,9 +70,9 @@ class OneDimDistance : public Distance */ OneDimDistance(const OneDimDistance& distance); - virtual Distance * clone() const override + virtual std::unique_ptr clone() const override { - return new OneDimDistance(*this); + return std::make_unique(*this); } DistanceType type() override { return DistanceType::OneDimDistance; } diff --git a/include/gwmodelpp/spatialweight/SpatialWeight.h b/include/gwmodelpp/spatialweight/SpatialWeight.h index 5a35e69c..de8fa29f 100644 --- a/include/gwmodelpp/spatialweight/SpatialWeight.h +++ b/include/gwmodelpp/spatialweight/SpatialWeight.h @@ -69,11 +69,46 @@ class SpatialWeight * @param weight 指向权重配置的指针。 * @param distance 指向距离配置的指针。 */ - SpatialWeight(const Weight* weight, const Distance* distance) - { - mWeight = weight->clone(); - mDistance = distance->clone(); - } + SpatialWeight(const Weight* weight, const Distance* distance): + mWeight(weight->clone()), + mDistance(distance->clone()) + {} + + /** + * \~english + * @brief Construct a new CGwmSpatialWeight object. + * + * @param weight Pointer to a weight configuration. + * @param distance Pointer to distance configuration. + * + * \~chinese + * @brief 构造一个新的 CGwmSpatialWeight 对象。 + * + * @param weight 指向权重配置的指针。 + * @param distance 指向距离配置的指针。 + */ + SpatialWeight(const std::unique_ptr& weight, const std::unique_ptr& distance): + mWeight(weight->clone()), + mDistance(distance->clone()) + {} + + /** + * \~english + * @brief Construct a new CGwmSpatialWeight object. + * + * @param weight Pointer to a weight configuration. + * @param distance Pointer to distance configuration. + * + * \~chinese + * @brief 构造一个新的 CGwmSpatialWeight 对象。 + * + * @param weight 指向权重配置的指针。 + * @param distance 指向距离配置的指针。 + */ + SpatialWeight(std::unique_ptr&& weight, std::unique_ptr&& distance): + mWeight(std::move(weight)), + mDistance(std::move(distance)) + {} /** * @brief Construct a new CGwmSpatialWeight object. @@ -87,11 +122,10 @@ class SpatialWeight * @param weight 指向权重配置的引用。 * @param distance 指向距离配置的引用。 */ - SpatialWeight(const Weight& weight, const Distance& distance) - { - mWeight = weight.clone(); - mDistance = distance.clone(); - } + SpatialWeight(const Weight& weight, const Distance& distance): + mWeight(weight.clone()), + mDistance(distance.clone()) + {} /** * \~english @@ -104,11 +138,10 @@ class SpatialWeight * * @param spatialWeight 被复制对象的引用。 */ - SpatialWeight(const SpatialWeight& spatialWeight) - { - mWeight = spatialWeight.mWeight->clone(); - mDistance = spatialWeight.mDistance->clone(); - } + SpatialWeight(const SpatialWeight& spatialWeight): + mWeight(spatialWeight.mWeight->clone()), + mDistance(spatialWeight.mDistance->clone()) + {} /** * @brief Move construct a new CGwmSpatialWeight object. @@ -120,14 +153,10 @@ class SpatialWeight * * @param other 被移动对象的引用。 */ - SpatialWeight(SpatialWeight&& other) - { - mWeight = other.mWeight; - mDistance = other.mDistance; - - other.mWeight = nullptr; - other.mDistance = nullptr; - } + SpatialWeight(SpatialWeight&& other): + mWeight(std::move(other.mWeight)), + mDistance(std::move(other.mDistance)) + {} /** * \~english @@ -136,7 +165,7 @@ class SpatialWeight * \~chinese * @brief 销毁 CGwmSpatialWeight 对象。 */ - virtual ~SpatialWeight(); + virtual ~SpatialWeight() {}; /** * \~english @@ -149,7 +178,7 @@ class SpatialWeight * * @return 指针 CGwmSpatialWeight::mWeight 。 */ - Weight *weight() const + const std::unique_ptr& weight() const { return mWeight; } @@ -167,12 +196,11 @@ class SpatialWeight * @param weight 指向 CGwmWeight 实例的指针。 * 获取该指针的控制权,并在类对象析构时释放该指针所指向的对象。 */ - void setWeight(Weight *weight) + void setWeight(const Weight *weight) { - if (weight && weight != mWeight) + if (weight && weight != mWeight.get()) { - if (mWeight) delete mWeight; - mWeight = weight->clone(); + mWeight = std::move(weight->clone()); } } @@ -189,10 +217,9 @@ class SpatialWeight * @param weight 指向 CGwmWeight 实例的指针。 * 指针所指向的对象会被克隆。 */ - void setWeight(Weight& weight) + void setWeight(const Weight& weight) { - if (mWeight) delete mWeight; - mWeight = weight.clone(); + mWeight = std::move(weight.clone()); } /** @@ -210,8 +237,12 @@ class SpatialWeight */ void setWeight(Weight&& weight) { - if (mWeight) delete mWeight; - mWeight = weight.clone(); + mWeight = std::move(weight.clone()); + } + + void setWeight(std::unique_ptr&& weight) + { + mWeight = std::move(weight); } /** @@ -228,7 +259,7 @@ class SpatialWeight * @return 转换后的 CGwmSpatialWeight::mWeight 指针。 */ template - T* weight() const { return nullptr; } + T& weight() const { return nullptr; } /** * \~english @@ -241,7 +272,7 @@ class SpatialWeight * * @return CGwmSpatialWeight::mDistance 指针。 */ - Distance *distance() const + const std::unique_ptr& distance() const { return mDistance; } @@ -259,12 +290,11 @@ class SpatialWeight * @param distance Pointer to CGwmDistance instance. * Con获取该指针的控制权,并在类对象析构时释放该指针所指向的对象。 */ - void setDistance(Distance *distance) + void setDistance(const Distance *distance) { - if (distance && distance != mDistance) + if (distance && distance != mDistance.get()) { - if (mDistance) delete mDistance; - mDistance = distance->clone(); + mDistance = std::move(distance->clone()); } } @@ -281,10 +311,9 @@ class SpatialWeight * @param distance 指向 CGwmDistance 实例的指针。 * 指针所指向的对象会被克隆。 */ - void setDistance(Distance& distance) + void setDistance(Distance&& distance) { - if (mDistance) delete mDistance; - mDistance = distance.clone(); + mDistance = std::move(distance.clone()); } /** @@ -302,8 +331,17 @@ class SpatialWeight */ void setDistance(Distance&& distance) { - if (mDistance) delete mDistance; - mDistance = distance.clone(); + mDistance = std::move(distance.clone()); + } + + void setDistance(const std::unique_ptr& distance) + { + mDistance = std::move(distance->clone()); + } + + void setDistance(std::unique_ptr&& distance) + { + mDistance = std::move(distance); } /** @@ -320,7 +358,7 @@ class SpatialWeight * @return 转换后的 CGwmSpatialWeight::mDistance 指针。 */ template - T* distance() const { return nullptr; } + T& distance() const { return nullptr; } public: @@ -439,8 +477,8 @@ class SpatialWeight virtual bool isValid(); private: - Weight* mWeight = nullptr; //!< Pointer to weight configuration. - Distance* mDistance = nullptr; //!< Pointer to distance configuration. + std::unique_ptr mWeight = nullptr; //!< Pointer to weight configuration. + std::unique_ptr mDistance = nullptr; //!< Pointer to distance configuration. }; /** @@ -455,9 +493,9 @@ class SpatialWeight * @return 转换后的 CGwmSpatialWeight::mWeight 指针。 */ template<> -inline BandwidthWeight* SpatialWeight::weight() const +inline BandwidthWeight& SpatialWeight::weight() const { - return static_cast(mWeight); + return static_cast(*mWeight.get()); } /** @@ -472,9 +510,9 @@ inline BandwidthWeight* SpatialWeight::weight() const * @return 转换后的 CGwmSpatialWeight::mDistance 指针。 */ template<> -inline CRSDistance* SpatialWeight::distance() const +inline CRSDistance& SpatialWeight::distance() const { - return static_cast(mDistance); + return static_cast(*mDistance.get()); } /** @@ -489,9 +527,9 @@ inline CRSDistance* SpatialWeight::distance() const * @return 转换后的 CGwmSpatialWeight::mDistance 指针。 */ template<> -inline CRSSTDistance* SpatialWeight::distance() const +inline CRSSTDistance& SpatialWeight::distance() const { - return static_cast(mDistance); + return static_cast(*mDistance.get()); } /** @@ -506,9 +544,9 @@ inline CRSSTDistance* SpatialWeight::distance() const * @return 转换后的 CGwmSpatialWeight::mDistance 指针。 */ template<> -inline MinkwoskiDistance* SpatialWeight::distance() const +inline MinkwoskiDistance& SpatialWeight::distance() const { - return static_cast(mDistance); + return static_cast(*mDistance.get()); } /** @@ -523,9 +561,9 @@ inline MinkwoskiDistance* SpatialWeight::distance() const * @return 转换后的 CGwmSpatialWeight::mDistance 指针。 */ template<> -inline DMatDistance* SpatialWeight::distance() const +inline DMatDistance& SpatialWeight::distance() const { - return static_cast(mDistance); + return static_cast(*mDistance.get()); } /** @@ -540,9 +578,9 @@ inline DMatDistance* SpatialWeight::distance() const * @return 转换后的 CGwmSpatialWeight::mDistance 指针。 */ template<> -inline OneDimDistance* SpatialWeight::distance() const +inline OneDimDistance& SpatialWeight::distance() const { - return static_cast(mDistance); + return static_cast(*mDistance.get()); } } diff --git a/include/gwmodelpp/spatialweight/Weight.h b/include/gwmodelpp/spatialweight/Weight.h index 781083ef..2988a666 100644 --- a/include/gwmodelpp/spatialweight/Weight.h +++ b/include/gwmodelpp/spatialweight/Weight.h @@ -52,7 +52,7 @@ class Weight * * @return \~english Newly created pointer \~chinese 新创建的指针 */ - virtual Weight* clone() const = 0; + virtual std::unique_ptr clone() const = 0; public: diff --git a/src/gwmodelpp/spatialweight/SpatialWeight.cpp b/src/gwmodelpp/spatialweight/SpatialWeight.cpp index 256f5485..03a0f6d0 100644 --- a/src/gwmodelpp/spatialweight/SpatialWeight.cpp +++ b/src/gwmodelpp/spatialweight/SpatialWeight.cpp @@ -2,34 +2,19 @@ using namespace gwm; - -SpatialWeight::~SpatialWeight() -{ - if (mWeight) delete mWeight; - if (mDistance) delete mDistance; - mWeight = nullptr; - mDistance = nullptr; -} - SpatialWeight &SpatialWeight::operator=(SpatialWeight &&spatialWeight) { if (this == &spatialWeight) return *this; - if (mWeight) delete mWeight; - if (mDistance) delete mDistance; - mWeight = spatialWeight.mWeight; - mDistance = spatialWeight.mDistance; - spatialWeight.mWeight = nullptr; - spatialWeight.mDistance = nullptr; + mWeight = std::move(spatialWeight.mWeight); + mDistance = std::move(spatialWeight.mDistance); return *this; } SpatialWeight &SpatialWeight::operator=(const SpatialWeight &spatialWeight) { if (this == &spatialWeight) return *this; - if (mWeight) delete mWeight; - if (mDistance) delete mDistance; - mWeight = spatialWeight.mWeight->clone(); - mDistance = spatialWeight.mDistance->clone(); + mWeight = std::move(spatialWeight.mWeight->clone()); + mDistance = std::move(spatialWeight.mDistance->clone()); return *this; } From dc8c6b20dc83262e5f83e9fdd08f6ce697e411a7 Mon Sep 17 00:00:00 2001 From: HPDell Date: Tue, 22 Jul 2025 18:13:46 +0100 Subject: [PATCH 2/5] fix: compile errors --- include/gwmodelpp/BandwidthSelector.h | 17 ++-- include/gwmodelpp/GTDR.h | 30 +++--- include/gwmodelpp/GTWR.h | 39 ++++---- include/gwmodelpp/GWCorrelation.h | 16 ++-- include/gwmodelpp/GWRBasic.h | 12 +-- include/gwmodelpp/GWRGeneralized.h | 17 ++-- include/gwmodelpp/GWRLocalCollinearity.h | 8 +- include/gwmodelpp/GWRMultiscale.h | 14 +-- include/gwmodelpp/IBandwidthSelectable.h | 14 +-- .../gwmodelpp/spatialweight/BandwidthWeight.h | 2 +- .../gwmodelpp/spatialweight/CRSSTDistance.h | 96 ++++++++++++++++--- include/gwmodelpp/spatialweight/Distance.h | 2 +- .../gwmodelpp/spatialweight/SpatialWeight.h | 16 ++-- include/gwmodelpp/spatialweight/Weight.h | 2 +- src/gwmodelcuda/GWRBasicGpuTask.cpp | 2 +- src/gwmodelpp/BandwidthSelector.cpp | 23 ++--- src/gwmodelpp/GTDR.cpp | 42 ++++---- src/gwmodelpp/GTWR.cpp | 92 +++++++++--------- src/gwmodelpp/GWCorrelation.cpp | 31 +++--- src/gwmodelpp/GWRBasic.cpp | 33 ++++--- src/gwmodelpp/GWRGeneralized.cpp | 19 ++-- src/gwmodelpp/GWRLocalCollinearity.cpp | 15 +-- src/gwmodelpp/GWRMultiscale.cpp | 50 +++++----- src/gwmodelpp/GWRRobust.cpp | 11 ++- src/gwmodelpp/GWRScalable.cpp | 44 ++++----- .../spatialweight/BandwidthWeight.cpp | 2 +- src/gwmodelpp/spatialweight/CRSSTDistance.cpp | 47 +-------- src/gwmodelpp/spatialweight/SpatialWeight.cpp | 4 +- test/mpi/testGWRBasicMpi.cpp | 4 +- test/mpi/testGWRMultiscaleMpi.cpp | 30 +++--- test/testGTDR.cpp | 16 ++-- test/testGTWR.cpp | 34 +++---- test/testGWCorrelation.cpp | 12 +-- test/testGWRBasic.cpp | 4 +- test/testGWRGeneralized.cpp | 6 +- test/testGWRLocalCollinearity.cpp | 4 +- test/testGWRMultiscale.cpp | 30 +++--- test/testGWRRobust.cpp | 4 +- 38 files changed, 430 insertions(+), 414 deletions(-) diff --git a/include/gwmodelpp/BandwidthSelector.h b/include/gwmodelpp/BandwidthSelector.h index 59f3ba9d..521d10c9 100644 --- a/include/gwmodelpp/BandwidthSelector.h +++ b/include/gwmodelpp/BandwidthSelector.h @@ -4,6 +4,7 @@ #include #include #include +#include "Status.h" #include "IBandwidthSelectable.h" #include "spatialweight/BandwidthWeight.h" @@ -21,7 +22,7 @@ class BandwidthSelector /** * @brief \~english Construct a new Bandwidth Selector object. \~chinese 构造一个新的 BandwidthSelector 对象。 */ - BandwidthSelector() {} + BandwidthSelector(const BandwidthWeight& bandwidth): mBandwidth(bandwidth), mOptimisedBandwidth(bandwidth) {} /** * @brief \~english Construct a new Bandwidth Selector object. \~chinese 构造一个新的 BandwidthSelector 对象。 @@ -30,7 +31,7 @@ class BandwidthSelector * @param lower \~english Lower bound \~chinese 下限 * @param upper \~english Upper bound \~chinese 上限 */ - BandwidthSelector(BandwidthWeight* bandwidth, double lower, double upper) : mBandwidth(bandwidth) , mLower(lower) , mUpper(upper) {} + BandwidthSelector(const BandwidthWeight& bandwidth, double lower, double upper) : mBandwidth(bandwidth), mOptimisedBandwidth(bandwidth), mLower(lower) , mUpper(upper) {} /** * @brief \~english Destroy the Bandwidth Selector object. \~chinese 销毁 BandwidthSelector 对象。 @@ -40,18 +41,19 @@ class BandwidthSelector public: /** - * @brief \~english Get the bandwidth. \~chinese 获取带宽。 + * @brief \~english Get the bandwidth. \~chinese 获取优化后的带宽。 * * @return BandwidthWeight* \~english Bandwidth \~chinese 带宽 */ - BandwidthWeight *bandwidth() const { return mBandwidth; } + // const BandwidthWeight *bandwidth() const { return mBandwidth; } + const BandwidthWeight& result() const { return mOptimisedBandwidth; } /** * @brief \~english Set the bandwidth. \~chinese 设置带宽。 * * @param bandwidth \~english Bandwidth \~chinese 带宽 */ - void setBandwidth(BandwidthWeight *bandwidth) { mBandwidth = bandwidth; } + // void setBandwidth(BandwidthWeight *bandwidth) { mBandwidth = bandwidth; } /** * @brief \~english Get the lower bound. \~chinese 获取下限。 @@ -96,10 +98,11 @@ class BandwidthSelector * @param instance \~english A pointer to a instance of type inherited from gwm::IBandwidthSelectable \~chinese 指向派生自 gwm::IBandwidthSelectable 类型对象的指针 * @return std::vector \~english Optimized bandwdith \~chinese 优选后的带宽 */ - BandwidthWeight* optimize(IBandwidthSelectable* instance); + Status optimize(IBandwidthSelectable* instance); private: - BandwidthWeight* mBandwidth; //!< \~english Bandwidth \~chinese 带宽 + const BandwidthWeight& mBandwidth; //!< \~english Bandwidth \~chinese 带宽 + BandwidthWeight mOptimisedBandwidth; double mLower; //!< \~english Lower bound \~chinese 下限 double mUpper; //!< \~english Upper bound \~chinese 上限 std::unordered_map mBandwidthCriterion; //!< \~english List of criterion values for each bandwidth \~chinese 带宽优选过程中每种带宽对应的指标值列表 diff --git a/include/gwmodelpp/GTDR.h b/include/gwmodelpp/GTDR.h index 2cf0fad8..04f22ce7 100644 --- a/include/gwmodelpp/GTDR.h +++ b/include/gwmodelpp/GTDR.h @@ -35,7 +35,7 @@ class GTDR : public SpatialAlgorithm, public IRegressionAnalysis, public IVarial AIC //!< AIC }; - typedef double (GTDR::*BandwidthCriterionCalculator)(const std::vector&); //!< \~english Calculator to get criterion for bandwidth optimization \~chinese 带宽优选指标值计算函数 + typedef double (GTDR::*BandwidthCriterionCalculator)(const std::vector>&); //!< \~english Calculator to get criterion for bandwidth optimization \~chinese 带宽优选指标值计算函数 typedef double (GTDR::*IndepVarCriterionCalculator)(const std::vector&); //!< \~english Calculator to get criterion for variable optimization \~chinese 变量优选指标值计算函数 @@ -367,7 +367,7 @@ class GTDR : public SpatialAlgorithm, public IRegressionAnalysis, public IVarial * @param bandwidths \~english Given bandwidths \~chinese 给定带宽值 * @return double \~english Criterion value \~chinese 指标值 */ - double bandwidthCriterion(const std::vector& bandwidths) + double bandwidthCriterion(const std::vector>& bandwidths) { return (this->*mBandwidthCriterionFunction)(bandwidths); } @@ -403,7 +403,7 @@ class GTDR : public SpatialAlgorithm, public IRegressionAnalysis, public IVarial * @param bandwidths \~english Given bandwidths \~chinese 给定带宽值 * @return double \~english Criterion value \~chinese 指标值 */ - double bandwidthCriterionAICSerial(const std::vector& bandwidths); + double bandwidthCriterionAICSerial(const std::vector>& bandwidths); /** * @brief \~english Non-parallel implementation of calculator to get CV criterion for given bandwidths. \~chinese 获取给定带宽值对应的CV值的非并行实现。 @@ -411,7 +411,7 @@ class GTDR : public SpatialAlgorithm, public IRegressionAnalysis, public IVarial * @param bandwidths \~english Given bandwidths \~chinese 给定带宽值 * @return double \~english Criterion value \~chinese 指标值 */ - double bandwidthCriterionCVSerial(const std::vector& bandwidths); + double bandwidthCriterionCVSerial(const std::vector>& bandwidths); /** * @brief \~english Non-parallel implementation of calculator to get AIC criterion for given variable combination. \~chinese 获取给定变量组合对应的AIC值的非并行实现。 @@ -451,7 +451,7 @@ class GTDR : public SpatialAlgorithm, public IRegressionAnalysis, public IVarial * @param bandwidths \~english Given bandwidths \~chinese 给定带宽值 * @return double \~english Criterion value \~chinese 指标值 */ - double bandwidthCriterionAICOmp(const std::vector& bandwidths); + double bandwidthCriterionAICOmp(const std::vector>& bandwidths); /** * @brief \~english Multithreading implementation of calculator to get CV criterion for given bandwidths. \~chinese 获取给定带宽值对应的CV值的多线程实现。 @@ -459,7 +459,7 @@ class GTDR : public SpatialAlgorithm, public IRegressionAnalysis, public IVarial * @param bandwidths \~english Given bandwidths \~chinese 给定带宽值 * @return double \~english Criterion value \~chinese 指标值 */ - double bandwidthCriterionCVOmp(const std::vector& bandwidths); + double bandwidthCriterionCVOmp(const std::vector>& bandwidths); /** * @brief \~english Multithreading implementation of calculator to get AIC criterion for given variable combination. \~chinese 获取给定变量组合对应的AIC值的多线程实现。 @@ -533,7 +533,7 @@ class GTDRBandwidthOptimizer struct Parameter { GTDR* instance; //!< \~english A GTDR instance \~chinese 一个 GTDR 实例 - std::vector* bandwidths; //!< \~english Bandwidths \~chinese 带宽 + std::vector> bandwidths; //!< \~english Bandwidths \~chinese 带宽 arma::uword featureCount; //!< \~english Total number of features \~chinese 要素总数 }; @@ -553,13 +553,13 @@ class GTDRBandwidthOptimizer * @param weights \~english Bandwidth weight \~chinese 带宽设置 * @return std::string \~english Information string \~chinese 信息字符串 */ - static std::string infoBandwidthCriterion(const std::vector& weights) + static std::string infoBandwidthCriterion(const std::vector>& weights) { std::size_t number = 1; std::vector labels(weights.size()); - std::transform(weights.cbegin(), weights.cend(), labels.begin(), [&number](const BandwidthWeight* bw) + std::transform(weights.cbegin(), weights.cend(), labels.begin(), [&number](const BandwidthWeight& bw) { - return std::to_string(number++) + ":" + (bw->adaptive() ? "adaptive" : "fixed"); + return std::to_string(number++) + ":" + (bw.adaptive() ? "adaptive" : "fixed"); }); return std::string(GWM_LOG_TAG_BANDWIDTH_CIRTERION) + strjoin(",", labels) + ",criterion"; } @@ -572,12 +572,12 @@ class GTDRBandwidthOptimizer * @param criterion \~english Criterion value \~chinese 指标值 * @return std::string \~english Information string \~chinese 信息字符串 */ - static std::string infoBandwidthCriterion(const std::vector& weights, const double criterion) + static std::string infoBandwidthCriterion(const std::vector>& weights, const double criterion) { std::vector labels(weights.size()); - std::transform(weights.cbegin(), weights.cend(), labels.begin(), [](const BandwidthWeight* bw) + std::transform(weights.cbegin(), weights.cend(), labels.begin(), [](const BandwidthWeight& bw) { - return std::to_string(bw->bandwidth()); + return std::to_string(bw.bandwidth()); }); return std::string(GWM_LOG_TAG_BANDWIDTH_CIRTERION) + strjoin(",", labels) + "," + std::to_string(criterion); } @@ -589,7 +589,7 @@ class GTDRBandwidthOptimizer * * @param weights \~english Initial values of bandwidths \~chinese 带宽初始值 */ - explicit GTDRBandwidthOptimizer(const std::vector& weights) : mBandwidths(weights) {} + explicit GTDRBandwidthOptimizer(const std::vector>& weights) : mBandwidths(weights) {} /** * @brief \~english Optimize bandwidth for a GTDR model. \~chinese 为 GTDR 模型优选带宽。 @@ -604,7 +604,7 @@ class GTDRBandwidthOptimizer const int optimize(GTDR* instance, arma::uword featureCount, std::size_t maxIter, double eps, double step); private: - std::vector mBandwidths; //!< \~english Bandwidths \~chinese 带宽 + const std::vector>& mBandwidths; //!< \~english Bandwidths \~chinese 带宽 }; } diff --git a/include/gwmodelpp/GTWR.h b/include/gwmodelpp/GTWR.h index 270cd713..94474432 100644 --- a/include/gwmodelpp/GTWR.h +++ b/include/gwmodelpp/GTWR.h @@ -50,7 +50,7 @@ class GTWR : public GWRBase, public IBandwidthSelectable, public IParallelizabl typedef arma::mat (GTWR::*PredictCalculator)(const arma::mat&, const arma::mat&, const arma::vec&);//!< \~english Predict function declaration. \~chinese 预测函数声明。 typedef arma::mat (GTWR::*FitCalculator)(const arma::mat&, const arma::vec&, arma::mat&, arma::vec&, arma::vec&, arma::mat&);//!< \~english Fit function declaration. \~chinese 拟合函数声明。 - typedef double (GTWR::*BandwidthSelectionCriterionCalculator)(BandwidthWeight*);//!< \~english Declaration of criterion calculator for bandwidth selection. \~chinese 带宽优选指标计算函数声明。 + typedef double (GTWR::*BandwidthSelectionCriterionCalculator)(const std::unique_ptr&);//!< \~english Declaration of criterion calculator for bandwidth selection. \~chinese 带宽优选指标计算函数声明。 typedef double (GTWR::*IndepVarsSelectCriterionCalculator)(const std::vector&);//!< \~english Declaration of criterion calculator for variable selection. \~chinese 变量优选指标计算函数声明。 /** @@ -78,19 +78,11 @@ class GTWR : public GWRBase, public IBandwidthSelectable, public IParallelizabl } const double getLambda() { - if (mStdistance != nullptr) { - return mStdistance->lambda(); - } else { - throw std::runtime_error("mStdistance is not initialized"); - } + return stDistance().lambda(); } const double getAngle(){ - if (mStdistance != nullptr) { - return mStdistance->angle(); - } else { - throw std::runtime_error("mStdistance is not initialized"); - } + return stDistance().angle(); } private: @@ -447,7 +439,7 @@ class GTWR : public GWRBase, public IBandwidthSelectable, public IParallelizabl #endif public: // Implement IBandwidthSelectable - Status getCriterion(BandwidthWeight* weight, double& criterion) override + Status getCriterion(const std::unique_ptr& weight, double& criterion) override { criterion = (this->*mBandwidthSelectionCriterionFunction)(weight); return mStatus; @@ -468,7 +460,7 @@ class GTWR : public GWRBase, public IBandwidthSelectable, public IParallelizabl * @param bandwidthWeight 指定的带宽。 * @return double 带宽优选的指标值。 */ - double bandwidthSizeCriterionCVSerial(BandwidthWeight* bandwidthWeight); + double bandwidthSizeCriterionCVSerial(const std::unique_ptr& bandwidthWeight); /** * \~english @@ -483,7 +475,7 @@ class GTWR : public GWRBase, public IBandwidthSelectable, public IParallelizabl * @param weigbandwidthWeightht 指定的带宽。 * @return double 带宽优选的指标值。 */ - double bandwidthSizeCriterionAICSerial(BandwidthWeight* bandwidthWeight); + double bandwidthSizeCriterionAICSerial(const std::unique_ptr& bandwidthWeight); #ifdef ENABLE_OPENMP /** @@ -499,7 +491,7 @@ class GTWR : public GWRBase, public IBandwidthSelectable, public IParallelizabl * @param bandwidthWeight 指定的带宽。 * @return double 带宽优选的指标值。 */ - double bandwidthSizeCriterionCVOmp(BandwidthWeight* bandwidthWeight); + double bandwidthSizeCriterionCVOmp(const std::unique_ptr& bandwidthWeight); /** * \~english @@ -514,7 +506,7 @@ class GTWR : public GWRBase, public IBandwidthSelectable, public IParallelizabl * @param bandwidthWeight 指定的带宽。 * @return double 带宽优选的指标值。 */ - double bandwidthSizeCriterionAICOmp(BandwidthWeight* bandwidthWeight); + double bandwidthSizeCriterionAICOmp(const std::unique_ptr& bandwidthWeight); #endif @@ -594,7 +586,7 @@ class GTWR : public GWRBase, public IBandwidthSelectable, public IParallelizabl * @param bandwidthWeight 传入带宽值,来获取权重,后续更方便改成多元优化. * @return double 返回优选以后的lambda值. */ - double lambdaAutoSelection(BandwidthWeight* bandwidthWeight); + double lambdaAutoSelection(const BandwidthWeight& bandwidthWeight); /** * \~english @@ -610,11 +602,11 @@ class GTWR : public GWRBase, public IBandwidthSelectable, public IParallelizabl * @param rsquare 根据输入的lambda值和带宽获取的R方值. * @return Status 算法运行状态。 */ - Status r_squareByLambda(BandwidthWeight* bandwidthWeight,double lambda, double& rsquare); + Status r_squareByLambda(const BandwidthWeight& bandwidthWeight,double lambda, double& rsquare); struct Parameter { GTWR* instance; // GTWR实例 - BandwidthWeight* bandwidth; // 带宽 + BandwidthWeight& bandwidth; // 带宽 double lambda; // lambda }; @@ -646,7 +638,7 @@ class GTWR : public GWRBase, public IBandwidthSelectable, public IParallelizabl * @param min_step 优化中的步长,设置为0.01(变化阈值为步长/1000) * @return 优化结果,一个向量:(lambda, bw). */ - arma::vec lambdaBwAutoSelection(BandwidthWeight* bandwidth, size_t max_iter, double min_step); + arma::vec lambdaBwAutoSelection(BandwidthWeight& bandwidth, size_t max_iter, double min_step); /** * \~english @@ -662,7 +654,7 @@ class GTWR : public GWRBase, public IBandwidthSelectable, public IParallelizabl * @param criterion BandwidthSelectionCriterionType类型,确定求的指标 * @return 对应类型的指标值 */ - double criterionByLambdaBw(BandwidthWeight* bandwidth, double lambda, BandwidthSelectionCriterionType criterion); + double criterionByLambdaBw(const BandwidthWeight& bandwidth, double lambda, BandwidthSelectionCriterionType criterion); public: /** @@ -681,6 +673,9 @@ class GTWR : public GWRBase, public IBandwidthSelectable, public IParallelizabl void setIsAutoselectLambdaBw(bool isAutoSelect) { mIsAutoselectLambdaBw = isAutoSelect; } +protected: + CRSSTDistance& stDistance() const { return mSpatialWeight.distance(); } + protected: bool mHasHatMatrix = true; //!< \~english Whether has hat-matrix. \~chinese 是否具有帽子矩阵。 @@ -709,8 +704,6 @@ class GTWR : public GWRBase, public IBandwidthSelectable, public IParallelizabl arma::vec vTimes; //!< \~english vectors for timestamp input. \~chinese 输入时间的向量。 - CRSSTDistance* mStdistance;//use to change spatial temporal distance including lambda - }; } diff --git a/include/gwmodelpp/GWCorrelation.h b/include/gwmodelpp/GWCorrelation.h index a8e42957..48c70792 100644 --- a/include/gwmodelpp/GWCorrelation.h +++ b/include/gwmodelpp/GWCorrelation.h @@ -231,7 +231,7 @@ class GWCorrelation : public SpatialMultiscaleAlgorithm, public IMultivariateAna public: //bandwidth selection - typedef double (GWCorrelation::*BandwidthSizeCriterionFunction)(BandwidthWeight*); //!< \~english Function to calculate the criterion for given bandwidth size. \~chinese 根据指定带宽大小计算对应指标值的函数。 + typedef double (GWCorrelation::*BandwidthSizeCriterionFunction)(const std::unique_ptr&); //!< \~english Function to calculate the criterion for given bandwidth size. \~chinese 根据指定带宽大小计算对应指标值的函数。 bool isAutoselectBandwidth() { return mIsAutoselectBandwidth; } @@ -294,7 +294,7 @@ class GWCorrelation : public SpatialMultiscaleAlgorithm, public IMultivariateAna * \~chinese * @brief 带宽优选指标计算函数声明。 */ - typedef double (GWCorrelation::*BandwidthSelectionCriterionCalculator)(BandwidthWeight*); + typedef double (GWCorrelation::*BandwidthSelectionCriterionCalculator)(const std::unique_ptr&); // bool isAutoselectBandwidth() const { return mIsAutoselectBandwidth; } // void setIsAutoselectBandwidth(bool isAutoSelect) { mIsAutoselectBandwidth = isAutoSelect; } @@ -354,7 +354,7 @@ class GWCorrelation : public SpatialMultiscaleAlgorithm, public IMultivariateAna * @param bandwidthWeight 指定的带宽。 * @return double 带宽优选的指标值。 */ - double bandwidthSizeCriterionCVSerial(BandwidthWeight* bandwidthWeight); + double bandwidthSizeCriterionCVSerial(const std::unique_ptr& bandwidthWeight); /** * \~english @@ -369,16 +369,16 @@ class GWCorrelation : public SpatialMultiscaleAlgorithm, public IMultivariateAna * @param weigbandwidthWeightht 指定的带宽。 * @return double 带宽优选的指标值。 */ - double bandwidthSizeCriterionAICSerial(BandwidthWeight* bandwidthWeight); + double bandwidthSizeCriterionAICSerial(const std::unique_ptr& bandwidthWeight); #ifdef ENABLE_OPENMP - double bandwidthSizeCriterionCVOmp(BandwidthWeight* bandwidthWeight); + double bandwidthSizeCriterionCVOmp(const std::unique_ptr& bandwidthWeight); - double bandwidthSizeCriterionAICOmp(BandwidthWeight* bandwidthWeight); + double bandwidthSizeCriterionAICOmp(const std::unique_ptr& bandwidthWeight); #endif public: // Implement IBandwidthSelectable - Status getCriterion(BandwidthWeight* weight, double& criterion) override + Status getCriterion(const std::unique_ptr& weight, double& criterion) override { criterion = (this->*mBandwidthSizeCriterion)(weight); return mStatus; @@ -464,7 +464,7 @@ class GWCorrelation : public SpatialMultiscaleAlgorithm, public IMultivariateAna protected: // std::vector mSpatialWeights; //!< Spatial weight configuration. - BandwidthWeight* bandwidth(size_t i) + BandwidthWeight& bandwidth(size_t i) { return mSpatialWeights[i].weight(); } diff --git a/include/gwmodelpp/GWRBasic.h b/include/gwmodelpp/GWRBasic.h index e333c491..24ac665c 100644 --- a/include/gwmodelpp/GWRBasic.h +++ b/include/gwmodelpp/GWRBasic.h @@ -52,7 +52,7 @@ class GWRBasic : public GWRBase, public IBandwidthSelectable, public IVarialbeSe typedef arma::mat (GWRBasic::*FitCoreSHatCalculator)(const arma::mat&, const arma::vec&, const SpatialWeight&, arma::vec&); //!< \~english Fit function declaration. \~chinese 拟合函数声明。 typedef arma::mat (GWRBasic::*FitCoreCVCalculator)(const arma::mat&, const arma::vec&, const SpatialWeight&); //!< \~english Fit function declaration. \~chinese 拟合函数声明。 - typedef double (GWRBasic::*BandwidthSelectionCriterionCalculator)(BandwidthWeight*); //!< \~english Declaration of criterion calculator for bandwidth selection. \~chinese 带宽优选指标计算函数声明。 + typedef double (GWRBasic::*BandwidthSelectionCriterionCalculator)(const std::unique_ptr&); //!< \~english Declaration of criterion calculator for bandwidth selection. \~chinese 带宽优选指标计算函数声明。 typedef double (GWRBasic::*IndepVarsSelectCriterionCalculator)(const std::vector&); //!< \~english Declaration of criterion calculator for variable selection. \~chinese 变量优选指标计算函数声明。 private: @@ -425,7 +425,7 @@ class GWRBasic : public GWRBase, public IBandwidthSelectable, public IVarialbeSe public: // Implement IBandwidthSelectable - Status getCriterion(BandwidthWeight* weight, double& criterion) override + Status getCriterion(const std::unique_ptr& weight, double& criterion) override { criterion = (this->*mBandwidthSelectionCriterionFunction)(weight); return mStatus; @@ -444,7 +444,7 @@ class GWRBasic : public GWRBase, public IBandwidthSelectable, public IVarialbeSe * @param bandwidthWeight 指定的带宽。 * @return double 带宽优选的指标值。 */ - double bandwidthSizeCriterionCV(BandwidthWeight* bandwidthWeight); + double bandwidthSizeCriterionCV(const std::unique_ptr& bandwidthWeight); /** * \~english @@ -459,7 +459,7 @@ class GWRBasic : public GWRBase, public IBandwidthSelectable, public IVarialbeSe * @param bandwidthWeight 指定的带宽。 * @return double 带宽优选的指标值。 */ - double bandwidthSizeCriterionAIC(BandwidthWeight* bandwidthWeight); + double bandwidthSizeCriterionAIC(const std::unique_ptr& bandwidthWeight); private: @@ -675,8 +675,8 @@ class GWRBasic : public GWRBase, public IBandwidthSelectable, public IVarialbeSe #ifdef ENABLE_MPI double indepVarsSelectionCriterionMpi(const std::vector& indepVars); - double bandwidthSizeCriterionCVMpi(BandwidthWeight* bandwidthWeight); - double bandwidthSizeCriterionAICMpi(BandwidthWeight* bandwidthWeight); + double bandwidthSizeCriterionCVMpi(const std::unique_ptr& bandwidthWeight); + double bandwidthSizeCriterionAICMpi(const std::unique_ptr& bandwidthWeight); arma::mat fitMpi(); #endif // ENABLE_MPI diff --git a/include/gwmodelpp/GWRGeneralized.h b/include/gwmodelpp/GWRGeneralized.h index f73cf090..6909d0f6 100644 --- a/include/gwmodelpp/GWRGeneralized.h +++ b/include/gwmodelpp/GWRGeneralized.h @@ -107,7 +107,7 @@ class GWRGeneralized : public GWRBase, public IBandwidthSelectable, public IPara CV //!< CV }; - typedef double (GWRGeneralized::*BandwidthSelectCriterionFunction)(BandwidthWeight *); //!< \~english Calculator to get criterion for bandwidth optimization \~chinese 带宽优选指标值计算函数 + typedef double (GWRGeneralized::*BandwidthSelectCriterionFunction)(const std::unique_ptr&); //!< \~english Calculator to get criterion for bandwidth optimization \~chinese 带宽优选指标值计算函数 typedef arma::mat (GWRGeneralized::*GGWRfitFunction)(const arma::mat& x, const arma::vec& y); //!< \~english Calculator for fitting \~chinese 拟合函数 typedef arma::vec (GWRGeneralized::*CalWtFunction)(const arma::mat &x, const arma::vec &y, arma::mat w); //!< \~english Calculator for weighting \~chinese 加权函数 @@ -126,7 +126,7 @@ class GWRGeneralized : public GWRBase, public IBandwidthSelectable, public IPara ~GWRGeneralized(){}; public: // IBandwidthSizeSelectable interface - Status getCriterion(BandwidthWeight *bandwidthWeight, double& criterion) override + Status getCriterion(const std::unique_ptr& bandwidthWeight, double& criterion) override { criterion = (this->*mBandwidthSelectCriterionFunction)(bandwidthWeight); return mStatus; @@ -273,7 +273,7 @@ class GWRGeneralized : public GWRBase, public IBandwidthSelectable, public IPara * @param bandwidths \~english Given bandwidths \~chinese 给定带宽值 * @return double \~english Criterion value \~chinese 指标值 */ - double bandwidthSizeGGWRCriterionCVSerial(BandwidthWeight *bandwidthWeight); + double bandwidthSizeGGWRCriterionCVSerial(const std::unique_ptr& bandwidthWeight); /** * @brief \~english Serial implementation of calculator to get AIC criterion for given bandwidths. \~chinese 获取给定带宽值对应的AIC值的串行实现。 @@ -281,7 +281,7 @@ class GWRGeneralized : public GWRBase, public IBandwidthSelectable, public IPara * @param bandwidths \~english Given bandwidths \~chinese 给定带宽值 * @return double \~english Criterion value \~chinese 指标值 */ - double bandwidthSizeGGWRCriterionAICSerial(BandwidthWeight *bandwidthWeight); + double bandwidthSizeGGWRCriterionAICSerial(const std::unique_ptr& bandwidthWeight); #ifdef ENABLE_OPENMP /** @@ -290,7 +290,7 @@ class GWRGeneralized : public GWRBase, public IBandwidthSelectable, public IPara * @param bandwidths \~english Given bandwidths \~chinese 给定带宽值 * @return double \~english Criterion value \~chinese 指标值 */ - double bandwidthSizeGGWRCriterionCVOmp(BandwidthWeight *bandwidthWeight); + double bandwidthSizeGGWRCriterionCVOmp(const std::unique_ptr& bandwidthWeight); /** * @brief \~english Multithreading implementation of calculator to get AIC criterion for given bandwidths. \~chinese 获取给定带宽值对应的AIC值的多线程实现。 @@ -298,7 +298,7 @@ class GWRGeneralized : public GWRBase, public IBandwidthSelectable, public IPara * @param bandwidths \~english Given bandwidths \~chinese 给定带宽值 * @return double \~english Criterion value \~chinese 指标值 */ - double bandwidthSizeGGWRCriterionAICOmp(BandwidthWeight *bandwidthWeight); + double bandwidthSizeGGWRCriterionAICOmp(const std::unique_ptr& bandwidthWeight); #endif public: @@ -365,7 +365,6 @@ class GWRGeneralized : public GWRBase, public IBandwidthSelectable, public IPara void setBandwidthSelectionCriterionType(const BandwidthSelectionCriterionType &bandwidthSelectionCriterionType); BandwidthCriterionList bandwidthSelectorCriterions() const; - BandwidthCriterionList mBandwidthSelectionCriterionList; BandwidthSelectionCriterionType bandwidthSelectionCriterionType() const; /** @@ -445,7 +444,7 @@ class GWRGeneralized : public GWRBase, public IBandwidthSelectable, public IPara bool mIsAutoselectBandwidth = false; //!< \~english Whether bandwidth optimization is enabled \~chinese 是否进行带宽优选 BandwidthSelectionCriterionType mBandwidthSelectionCriterionType = BandwidthSelectionCriterionType::AIC; //!< \~english Type of criterion for bandwidth optimization \~chinese 带宽优选指标类型 BandwidthSelectCriterionFunction mBandwidthSelectCriterionFunction = &GWRGeneralized::bandwidthSizeGGWRCriterionCVSerial; //!< \~english Calculator to get criterion for given bandwidth value \~chinese 用于根据给定带宽值计算指标值的函数 - BandwidthSelector mBandwidthSizeSelector; //!< \~english Bandwidth size selector \~chinese 带宽选择器 + BandwidthCriterionList mBandwidthSelectionCriterionList; double mBandwidthLastCriterion = DBL_MAX; //!< \~english Last criterion for bandwidth selection. \~chinese 上一次带宽优选的有效指标值。 ParallelType mParallelType = ParallelType::SerialOnly; //!< \~english Type of parallelization \~chinese 并行方法类型 @@ -499,7 +498,7 @@ inline void GWRGeneralized::setMaxiter(size_t maxiter) inline BandwidthCriterionList GWRGeneralized::bandwidthSelectorCriterions() const { - return mBandwidthSizeSelector.bandwidthCriterion(); + return mBandwidthSelectionCriterionList; } inline bool GWRGeneralized::hasHatMatrix() const diff --git a/include/gwmodelpp/GWRLocalCollinearity.h b/include/gwmodelpp/GWRLocalCollinearity.h index e80bc2fa..52ca7c0c 100644 --- a/include/gwmodelpp/GWRLocalCollinearity.h +++ b/include/gwmodelpp/GWRLocalCollinearity.h @@ -32,7 +32,7 @@ class GWRLocalCollinearity : public GWRBase, public IBandwidthSelectable, public CV //!< CV }; - typedef double (GWRLocalCollinearity::*BandwidthSelectionCriterionCalculator)(BandwidthWeight*); //!< \~english Calculator to get criterion for bandwidth optimization \~chinese 带宽优选指标值计算函数 + typedef double (GWRLocalCollinearity::*BandwidthSelectionCriterionCalculator)(const std::unique_ptr&); //!< \~english Calculator to get criterion for bandwidth optimization \~chinese 带宽优选指标值计算函数 typedef arma::mat (GWRLocalCollinearity::*FitCalculator)(const arma::mat&, const arma::vec&, arma::vec&, arma::vec&); //!< \~english Calculator to predict \~chinese 用于预测的函数 typedef arma::mat (GWRLocalCollinearity::*PredictCalculator)(const arma::mat&, const arma::mat&, const arma::vec&); //!< \~english Calculator to predict \~chinese 用于预测的函数 @@ -208,7 +208,7 @@ class GWRLocalCollinearity : public GWRBase, public IBandwidthSelectable, public */ void setBandwidthSelectionCriterion(const BandwidthSelectionCriterionType& criterion); - Status getCriterion(BandwidthWeight *bandwidthWeight, double& criterion) override + Status getCriterion(const std::unique_ptr& bandwidthWeight, double& criterion) override { criterion = (this->*mBandwidthSelectionCriterionFunction)(bandwidthWeight); return mStatus; @@ -317,7 +317,7 @@ class GWRLocalCollinearity : public GWRBase, public IBandwidthSelectable, public * @param bandwidths \~english Given bandwidths \~chinese 给定带宽值 * @return double \~english Criterion value \~chinese 指标值 */ - double bandwidthSizeCriterionCVSerial(BandwidthWeight* bandwidthWeight); + double bandwidthSizeCriterionCVSerial(const std::unique_ptr& bandwidthWeight); #ifdef ENABLE_OPENMP /** @@ -326,7 +326,7 @@ class GWRLocalCollinearity : public GWRBase, public IBandwidthSelectable, public * @param bandwidths \~english Given bandwidths \~chinese 给定带宽值 * @return double \~english Criterion value \~chinese 指标值 */ - double bandwidthSizeCriterionCVOmp(BandwidthWeight* bandwidthWeight); + double bandwidthSizeCriterionCVOmp(const std::unique_ptr& bandwidthWeight); #endif private: diff --git a/include/gwmodelpp/GWRMultiscale.h b/include/gwmodelpp/GWRMultiscale.h index b3d0f5d1..dd8a3f14 100644 --- a/include/gwmodelpp/GWRMultiscale.h +++ b/include/gwmodelpp/GWRMultiscale.h @@ -88,7 +88,7 @@ class GWRMultiscale : public SpatialMultiscaleAlgorithm, static std::unordered_map BackFittingCriterionTypeNameMapper; //!< \~english A mapper from backfitting convergence criterion types to their names. \~chinese 后向迭代算法收敛指标类型到其名称的映射表。 - typedef double (GWRMultiscale::*BandwidthSizeCriterionFunction)(BandwidthWeight*); //!< \~english Function to calculate the criterion for given bandwidth size. \~chinese 根据指定带宽大小计算对应指标值的函数。 + typedef double (GWRMultiscale::*BandwidthSizeCriterionFunction)(const std::unique_ptr&); //!< \~english Function to calculate the criterion for given bandwidth size. \~chinese 根据指定带宽大小计算对应指标值的函数。 typedef arma::vec (GWRMultiscale::*FitVarFunction)(const size_t); //!< \~english Function to fit a model for the given variable. \~chinese 根据给定变量拟合模型的函数。 @@ -574,7 +574,7 @@ class GWRMultiscale : public SpatialMultiscaleAlgorithm, public: // IBandwidthSizeSelectable interface - Status getCriterion(BandwidthWeight* weight, double& criterion) override + Status getCriterion(const std::unique_ptr& weight, double& criterion) override { criterion = (this->*mBandwidthSizeCriterion)(weight); return mStatus; @@ -640,7 +640,7 @@ class GWRMultiscale : public SpatialMultiscaleAlgorithm, * @param i 带宽索引值。 * @return BandwidthWeight* 第 \f$i\f$ 个带宽。 */ - BandwidthWeight* bandwidth(size_t i) + BandwidthWeight& bandwidth(size_t i) { return mSpatialWeights[i].weight(); } @@ -679,7 +679,7 @@ class GWRMultiscale : public SpatialMultiscaleAlgorithm, * @param bandwidthWeight 带宽值。 * @return double CV指标值。 */ - double bandwidthSizeCriterionVarCVBase(BandwidthWeight* bandwidthWeight); + double bandwidthSizeCriterionVarCVBase(const std::unique_ptr& bandwidthWeight); /** * \~english @@ -694,7 +694,7 @@ class GWRMultiscale : public SpatialMultiscaleAlgorithm, * @param bandwidthWeight 带宽值。 * @return double AIC指标值。 */ - double bandwidthSizeCriterionVarAICBase(BandwidthWeight* bandwidthWeight); + double bandwidthSizeCriterionVarAICBase(const std::unique_ptr& bandwidthWeight); /** * \~english @@ -760,8 +760,8 @@ class GWRMultiscale : public SpatialMultiscaleAlgorithm, #ifdef ENABLE_MPI arma::vec fitVarMpi(const size_t var); - double bandwidthSizeCriterionVarCVMpi(BandwidthWeight* bandwidthWeight); - double bandwidthSizeCriterionVarAICMpi(BandwidthWeight* bandwidthWeight); + double bandwidthSizeCriterionVarCVMpi(const std::unique_ptr& bandwidthWeight); + double bandwidthSizeCriterionVarAICMpi(const std::unique_ptr& bandwidthWeight); #endif // ENABLE_MPI private: diff --git a/include/gwmodelpp/IBandwidthSelectable.h b/include/gwmodelpp/IBandwidthSelectable.h index b1a6cb1a..73d3bea7 100644 --- a/include/gwmodelpp/IBandwidthSelectable.h +++ b/include/gwmodelpp/IBandwidthSelectable.h @@ -27,9 +27,9 @@ struct IBandwidthSelectable * @param weight \~english Bandwidth weight \~chinese 带宽设置 * @return std::string \~english Information string \~chinese 信息字符串 */ - static std::string infoBandwidthCriterion(const BandwidthWeight* weight) + static std::string infoBandwidthCriterion(const BandwidthWeight& weight) { - return std::string(GWM_LOG_TAG_BANDWIDTH_CIRTERION) + (weight->adaptive() ? "adaptive" : "fixed") + ",criterion"; + return std::string(GWM_LOG_TAG_BANDWIDTH_CIRTERION) + (weight.adaptive() ? "adaptive" : "fixed") + ",criterion"; } /** @@ -40,12 +40,12 @@ struct IBandwidthSelectable * @param value \~english Criterion value \~chinese 指标值 * @return std::string \~english Information string \~chinese 信息字符串 */ - static std::string infoBandwidthCriterion(const BandwidthWeight* weight, const double value) + static std::string infoBandwidthCriterion(const BandwidthWeight& weight, const double value) { - if (weight->adaptive()) - return std::string(GWM_LOG_TAG_BANDWIDTH_CIRTERION) + std::to_string(int(weight->bandwidth())) + "," + std::to_string(value); + if (weight.adaptive()) + return std::string(GWM_LOG_TAG_BANDWIDTH_CIRTERION) + std::to_string(int(weight.bandwidth())) + "," + std::to_string(value); else - return std::string(GWM_LOG_TAG_BANDWIDTH_CIRTERION) + std::to_string(weight->bandwidth()) + "," + std::to_string(value); + return std::string(GWM_LOG_TAG_BANDWIDTH_CIRTERION) + std::to_string(weight.bandwidth()) + "," + std::to_string(value); } /** @@ -63,7 +63,7 @@ struct IBandwidthSelectable * @param criterion [出参] 带宽优选的指标值。 * @param Status 算法运行状态。 */ - virtual Status getCriterion(BandwidthWeight* weight, double& criterion) = 0; + virtual Status getCriterion(const std::unique_ptr& weight, double& criterion) = 0; }; typedef std::vector > BandwidthCriterionList; //!< \~english A list of bandwidth criterions for all attempt bandwidth values. \~chinese 所有尝试的带宽对应的指标值列表 diff --git a/include/gwmodelpp/spatialweight/BandwidthWeight.h b/include/gwmodelpp/spatialweight/BandwidthWeight.h index 084ed530..4aa2d0b1 100644 --- a/include/gwmodelpp/spatialweight/BandwidthWeight.h +++ b/include/gwmodelpp/spatialweight/BandwidthWeight.h @@ -178,7 +178,7 @@ class BandwidthWeight : public Weight } public: - virtual arma::vec weight(arma::vec dist) override; + virtual arma::vec weight(arma::vec dist) const override; #ifdef ENABLE_CUDA virtual cudaError_t weight(double* d_dists, double* d_weights, size_t elems) override; diff --git a/include/gwmodelpp/spatialweight/CRSSTDistance.h b/include/gwmodelpp/spatialweight/CRSSTDistance.h index 07cc20d0..02a5e264 100644 --- a/include/gwmodelpp/spatialweight/CRSSTDistance.h +++ b/include/gwmodelpp/spatialweight/CRSSTDistance.h @@ -19,7 +19,7 @@ class CRSSTDistance : public Distance * @brief \~english parameters used in calculating. * \~chinese 距离计算的输入参数类型:空间距离,时间距离,计算序号,λ,余弦值的角度(默认为π/2) */ - typedef arma::vec (*CalculatorType)(Distance*, gwm::OneDimDistance*, arma::uword, double, double); + typedef arma::vec (*CalculatorType)(const std::unique_ptr&, const std::unique_ptr&, arma::uword, double, double); /** * @brief \~english Calculate temporal and spatial distance, Orthogonal Distance @@ -37,7 +37,7 @@ class CRSSTDistance : public Distance * \~chinese 参数取默认值。 * @return arma::vec \~english Distance vector \~chinese 计算得到的距离向量 */ - static arma::vec OrthogonalSTDistance(Distance* spatial, gwm::OneDimDistance* temporal, arma::uword focus, double lambda, double angle); + static arma::vec OrthogonalSTDistance(const std::unique_ptr& spatial, const std::unique_ptr& temporal, arma::uword focus, double lambda, double angle); /** * @brief \~english Calculate temporal and spatial distance with angle, Oblique Distance @@ -55,25 +55,99 @@ class CRSSTDistance : public Distance * \~chinese 默认值是π/2,给函数提供angle值,计算斜交时空距离 * @return arma::vec \~english Distance vector \~chinese 计算得到的距离向量 */ - static arma::vec ObliqueSTDistance(Distance* spatial, gwm::OneDimDistance* temporal, arma::uword focus, double lambda, double angle); + static arma::vec ObliqueSTDistance(const std::unique_ptr& spatial, const std::unique_ptr& temporal, arma::uword focus, double lambda, double angle); public: /** * @brief Construct. */ - CRSSTDistance(); + CRSSTDistance() : + mSpatialDistance(nullptr), + mTemporalDistance(nullptr), + mLambda(0.0), + mAngle(arma::datum::pi / 2.0) + { + mCalculator = &OrthogonalSTDistance; + }; + + explicit CRSSTDistance(const Distance& spatialDistance, const OneDimDistance& temporalDistance, double lambda): + mSpatialDistance(spatialDistance.clone()), + mTemporalDistance(static_cast(temporalDistance.clone().release())), + mLambda(lambda), + mAngle(arma::datum::pi / 2.0), + mCalculator(&OrthogonalSTDistance) + {} + + explicit CRSSTDistance(const Distance& spatialDistance, const OneDimDistance& temporalDistance, double lambda, double angle): + CRSSTDistance(spatialDistance, temporalDistance, lambda) + { + mAngle = angle, + mCalculator = (abs(mAngle - arma::datum::pi / 2.0) < 1e-15) ? &OrthogonalSTDistance : &ObliqueSTDistance; + } + + explicit CRSSTDistance(Distance&& spatialDistance, OneDimDistance&& temporalDistance, double lambda): + mSpatialDistance(spatialDistance.clone()), + mTemporalDistance(static_cast(temporalDistance.clone().release())), + mLambda(lambda), + mAngle(arma::datum::pi / 2.0), + mCalculator(&OrthogonalSTDistance) + {} + + explicit CRSSTDistance(Distance&& spatialDistance, OneDimDistance&& temporalDistance, double lambda, double angle): + CRSSTDistance(spatialDistance, temporalDistance, lambda) + { + mAngle = angle, + mCalculator = (abs(mAngle - arma::datum::pi / 2.0) < 1e-15) ? &OrthogonalSTDistance : &ObliqueSTDistance; + } - explicit CRSSTDistance(Distance* spatialDistance, gwm::OneDimDistance* temporalDistance, double lambda); + explicit CRSSTDistance(const std::unique_ptr& spatialDistance, const std::unique_ptr& temporalDistance, double lambda): + mSpatialDistance(spatialDistance->clone()), + mTemporalDistance(static_cast(temporalDistance->clone().release())), + mLambda(lambda), + mAngle(arma::datum::pi / 2.0), + mCalculator(&OrthogonalSTDistance) + {} - explicit CRSSTDistance(Distance* spatialDistance, gwm::OneDimDistance* temporalDistance, double lambda, double angle); + explicit CRSSTDistance(const std::unique_ptr& spatialDistance, const std::unique_ptr& temporalDistance, double lambda, double angle): + CRSSTDistance(spatialDistance, temporalDistance, lambda) + { + mAngle = angle, + mCalculator = (abs(mAngle - arma::datum::pi / 2.0) < 1e-15) ? &OrthogonalSTDistance : &ObliqueSTDistance; + } + + explicit CRSSTDistance(std::unique_ptr&& spatialDistance, std::unique_ptr&& temporalDistance, double lambda): + mSpatialDistance(std::move(spatialDistance)), + mTemporalDistance(std::move(temporalDistance)), + mLambda(lambda), + mAngle(arma::datum::pi / 2.0), + mCalculator(&OrthogonalSTDistance) + {} + + explicit CRSSTDistance(std::unique_ptr&& spatialDistance, std::unique_ptr&& temporalDistance, double lambda, double angle): + CRSSTDistance(std::move(spatialDistance), std::move(temporalDistance), lambda) + { + mAngle = angle, + mCalculator = (abs(mAngle - arma::datum::pi / 2.0) < 1e-15) ? &OrthogonalSTDistance : &ObliqueSTDistance; + } /** * @brief Copy construct. * * @param distance Refernce to object for copying. */ - CRSSTDistance(const CRSSTDistance& distance); + CRSSTDistance(const CRSSTDistance& distance): + mSpatialDistance(distance.mSpatialDistance->clone()), + mTemporalDistance(static_cast(distance.mTemporalDistance->clone().release())), + mAngle(distance.mAngle), + mCalculator(distance.mCalculator) + { + if (distance.mLambda >= 0 && distance.mLambda <= 1) + { + mLambda = distance.mLambda; + } + else throw std::runtime_error("The lambda must be in [0,1]."); + } std::unique_ptr clone() const override { @@ -113,9 +187,9 @@ class CRSSTDistance : public Distance //const gwm::CRSDistance* spatialDistance() const { return mSpatialDistance; } - const Distance* spatialDistance() const { return mSpatialDistance; } + const std::unique_ptr& spatialDistance() const { return mSpatialDistance; } - const gwm::OneDimDistance* temporalDistance() const { return mTemporalDistance; } + const std::unique_ptr& temporalDistance() const { return mTemporalDistance; } // unused code to set lambda const double lambda(){ return mLambda; } @@ -134,8 +208,8 @@ class CRSSTDistance : public Distance } protected: - Distance* mSpatialDistance = nullptr; //!< \~english Pointer to instance for spatial distance \~chinese 指向空间距离的指针 - gwm::OneDimDistance* mTemporalDistance = nullptr; //!< \~english Pointer to instance for temporal distance \~chinese 指向时间距离的指针 + std::unique_ptr mSpatialDistance = nullptr; //!< \~english Pointer to instance for spatial distance \~chinese 指向空间距离的指针 + std::unique_ptr mTemporalDistance = nullptr; //!< \~english Pointer to instance for temporal distance \~chinese 指向时间距离的指针 double mLambda = 0.0; //!< \~english Weight of temporal distance \~chinese 时间距离的权重 double mAngle = arma::datum::pi / 2; //!< \~english Angle of spatial distance and temporal distance \~chinese 斜交时空距离的角度 diff --git a/include/gwmodelpp/spatialweight/Distance.h b/include/gwmodelpp/spatialweight/Distance.h index 3cbcc14c..00c290be 100644 --- a/include/gwmodelpp/spatialweight/Distance.h +++ b/include/gwmodelpp/spatialweight/Distance.h @@ -47,7 +47,7 @@ class Distance /** * @brief \~english Types of distance. \~chinese 距离度量类型。 */ - enum DistanceType + enum class DistanceType { CRSDistance, //!< \~english Distance according to coordinate reference system \~chinese 坐标系距离 MinkwoskiDistance, //!< \~english Minkwoski distance \~chinese Minkwoski 距离 diff --git a/include/gwmodelpp/spatialweight/SpatialWeight.h b/include/gwmodelpp/spatialweight/SpatialWeight.h index de8fa29f..4698cabf 100644 --- a/include/gwmodelpp/spatialweight/SpatialWeight.h +++ b/include/gwmodelpp/spatialweight/SpatialWeight.h @@ -200,7 +200,7 @@ class SpatialWeight { if (weight && weight != mWeight.get()) { - mWeight = std::move(weight->clone()); + mWeight = weight->clone(); } } @@ -219,7 +219,7 @@ class SpatialWeight */ void setWeight(const Weight& weight) { - mWeight = std::move(weight.clone()); + mWeight = weight.clone(); } /** @@ -237,7 +237,7 @@ class SpatialWeight */ void setWeight(Weight&& weight) { - mWeight = std::move(weight.clone()); + mWeight = weight.clone(); } void setWeight(std::unique_ptr&& weight) @@ -294,7 +294,7 @@ class SpatialWeight { if (distance && distance != mDistance.get()) { - mDistance = std::move(distance->clone()); + mDistance = distance->clone(); } } @@ -311,9 +311,9 @@ class SpatialWeight * @param distance 指向 CGwmDistance 实例的指针。 * 指针所指向的对象会被克隆。 */ - void setDistance(Distance&& distance) + void setDistance(const Distance& distance) { - mDistance = std::move(distance.clone()); + mDistance = distance.clone(); } /** @@ -331,12 +331,12 @@ class SpatialWeight */ void setDistance(Distance&& distance) { - mDistance = std::move(distance.clone()); + mDistance = distance.clone(); } void setDistance(const std::unique_ptr& distance) { - mDistance = std::move(distance->clone()); + mDistance = distance->clone(); } void setDistance(std::unique_ptr&& distance) diff --git a/include/gwmodelpp/spatialweight/Weight.h b/include/gwmodelpp/spatialweight/Weight.h index 2988a666..82f2efbc 100644 --- a/include/gwmodelpp/spatialweight/Weight.h +++ b/include/gwmodelpp/spatialweight/Weight.h @@ -62,7 +62,7 @@ class Weight * @param dist \~english According distance vector \~chinese 距离向量 * @return \~english Weight vector \~chinese 权重向量 */ - virtual arma::vec weight(arma::vec dist) = 0; + virtual arma::vec weight(arma::vec dist) const = 0; #ifdef ENABLE_CUDA bool useCuda() { return mUseCuda; } diff --git a/src/gwmodelcuda/GWRBasicGpuTask.cpp b/src/gwmodelcuda/GWRBasicGpuTask.cpp index 559df40c..4844f7a9 100644 --- a/src/gwmodelcuda/GWRBasicGpuTask.cpp +++ b/src/gwmodelcuda/GWRBasicGpuTask.cpp @@ -29,7 +29,7 @@ bool GWRBasicGpuTask::fit(bool hasIntercept) if (mIsOptimizeBandwidth) { - mOptimizedBandwidth = algorithm.spatialWeight().weight()->bandwidth(); + mOptimizedBandwidth = algorithm.spatialWeight().weight().bandwidth(); } if (mIsOptimizeVariables) diff --git a/src/gwmodelpp/BandwidthSelector.cpp b/src/gwmodelpp/BandwidthSelector.cpp index fbd47670..07022fb8 100644 --- a/src/gwmodelpp/BandwidthSelector.cpp +++ b/src/gwmodelpp/BandwidthSelector.cpp @@ -3,12 +3,12 @@ using namespace std; using namespace gwm; -BandwidthWeight* BandwidthSelector::optimize(IBandwidthSelectable* instance) +Status BandwidthSelector::optimize(IBandwidthSelectable* instance) { - BandwidthWeight* w1 = static_cast(mBandwidth->clone()); - BandwidthWeight* w2 = static_cast(mBandwidth->clone()); + unique_ptr w1 { static_cast(mBandwidth.clone().release()) }; + unique_ptr w2 { static_cast(mBandwidth.clone().release()) }; double xU = mUpper, xL = mLower; - bool adaptBw = mBandwidth->adaptive(); + bool adaptBw = mBandwidth.adaptive(); const double eps = 1e-4; const double R = (sqrt(5)-1)/2; int iter = 0; @@ -20,9 +20,9 @@ BandwidthWeight* BandwidthSelector::optimize(IBandwidthSelectable* instance) double f1 = DBL_MAX, f2 = DBL_MAX; Status s1 = instance->getCriterion(w1, f1); Status s2 = instance->getCriterion(w2, f2); - if (!(s1 == Status::Success && s2 == Status::Success)) + if (s1 == Status::Terminated || s2 == Status::Terminated) { - return mBandwidth; + return Status::Terminated; } if (f1 == DBL_MAX && f2 == DBL_MAX) { @@ -64,19 +64,14 @@ BandwidthWeight* BandwidthSelector::optimize(IBandwidthSelectable* instance) xopt = (f1 < f2) ? x1 : x2; d1 = f2 - f1; } - delete w1; - delete w2; if (s1 == Status::Success && s2 == Status::Success) { - BandwidthWeight* wopt = new BandwidthWeight(); - wopt->setKernel(mBandwidth->kernel()); - wopt->setAdaptive(mBandwidth->adaptive()); - wopt->setBandwidth(xopt); - return wopt; + mOptimisedBandwidth.setBandwidth(xopt); + return Status::Success; } else { - return mBandwidth; + return Status::Success; } } diff --git a/src/gwmodelpp/GTDR.cpp b/src/gwmodelpp/GTDR.cpp index b82ac21a..d9dcb009 100644 --- a/src/gwmodelpp/GTDR.cpp +++ b/src/gwmodelpp/GTDR.cpp @@ -69,16 +69,16 @@ mat GTDR::fit() GWM_LOG_STAGE("Bandwidth selection"); for (auto&& sw : mSpatialWeights) { - BandwidthWeight* bw = sw.weight(); + BandwidthWeight& bw = sw.weight(); // Set Initial value - double lower = bw->adaptive() ? nVars + 1 : sw.distance()->minDistance(); - double upper = bw->adaptive() ? nDp : sw.distance()->maxDistance(); - if (bw->bandwidth() <= lower || bw->bandwidth() >= upper) + double lower = bw.adaptive() ? nVars + 1 : sw.distance()->minDistance(); + double upper = bw.adaptive() ? nDp : sw.distance()->maxDistance(); + if (bw.bandwidth() <= lower || bw.bandwidth() >= upper) { - bw->setBandwidth(upper * 0.618); + bw.setBandwidth(upper * 0.618); } } - vector bws; + vector> bws; for (auto&& iter : mSpatialWeights) { bws.push_back(iter.weight()); @@ -319,7 +319,7 @@ mat GTDR::fitOmp(const mat& x, const vec& y, mat& betasSE, vec& shat, vec& qdiag } #endif -double GTDR::bandwidthCriterionCVSerial(const vector& bandwidths) +double GTDR::bandwidthCriterionCVSerial(const vector>& bandwidths) { uword nDp = mCoords.n_rows, nDim = mCoords.n_cols; double cv = 0.0; @@ -333,7 +333,7 @@ double GTDR::bandwidthCriterionCVSerial(const vector& bandwidt for (size_t m = 0; m < nDim; m++) { vec d_m = mSpatialWeights[m].distance()->distance(i); - vec w_m = bandwidths[m]->weight(d_m); + vec w_m = bandwidths[m].get().weight(d_m); w = w % w_m; } w(i) = 0.0; @@ -366,7 +366,7 @@ double GTDR::bandwidthCriterionCVSerial(const vector& bandwidt } #ifdef ENABLE_OPENMP -double GTDR::bandwidthCriterionCVOmp(const vector& bandwidths) +double GTDR::bandwidthCriterionCVOmp(const vector>& bandwidths) { uword nDp = mCoords.n_rows, nDim = mCoords.n_cols; vec cv_all(mOmpThreadNum, arma::fill::zeros); @@ -382,7 +382,7 @@ double GTDR::bandwidthCriterionCVOmp(const vector& bandwidths) for (size_t m = 0; m < nDim; m++) { vec d_m = mSpatialWeights[m].distance()->distance(i); - vec w_m = bandwidths[m]->weight(d_m); + vec w_m = bandwidths[m].get().weight(d_m); w = w % w_m; } w(i) = 0.0; @@ -417,7 +417,7 @@ double GTDR::bandwidthCriterionCVOmp(const vector& bandwidths) } #endif -double GTDR::bandwidthCriterionAICSerial(const vector& bandwidths) +double GTDR::bandwidthCriterionAICSerial(const vector>& bandwidths) { uword nDp = mCoords.n_rows, nDim = mCoords.n_cols, nVar = mX.n_cols; mat betas(nVar, nDp, fill::zeros); @@ -432,7 +432,7 @@ double GTDR::bandwidthCriterionAICSerial(const vector& bandwid for (size_t m = 0; m < nDim; m++) { vec d_m = mSpatialWeights[m].distance()->distance(i); - vec w_m = bandwidths[m]->weight(d_m); + vec w_m = bandwidths[m].get().weight(d_m); w = w % w_m; } mat xtw = (mX.each_col() % w).t(); @@ -466,7 +466,7 @@ double GTDR::bandwidthCriterionAICSerial(const vector& bandwid } #ifdef ENABLE_OPENMP -double GTDR::bandwidthCriterionAICOmp(const vector& bandwidths) +double GTDR::bandwidthCriterionAICOmp(const vector>& bandwidths) { uword nDp = mCoords.n_rows, nDim = mCoords.n_cols, nVar = mX.n_cols; mat betas(nVar, nDp, arma::fill::zeros); @@ -484,7 +484,7 @@ double GTDR::bandwidthCriterionAICOmp(const vector& bandwidths for (size_t m = 0; m < nDim; m++) { vec d_m = mSpatialWeights[m].distance()->distance(i); - vec w_m = bandwidths[m]->weight(d_m); + vec w_m = bandwidths[m].get().weight(d_m); w = w % w_m; } mat xtw = (mX.each_col() % w).t(); @@ -533,7 +533,7 @@ double GTDR::indepVarCriterionSerial(const vector& indepVars) { for (auto &&sw : mSpatialWeights) { - if (sw.weight()->bandwidth() == 0.0) isGlobal = true; + if (sw.weight().bandwidth() == 0.0) isGlobal = true; } } if (isGlobal) @@ -614,7 +614,7 @@ double GTDR::indepVarCriterionOmp(const vector& indepVars) { for (auto &&sw : mSpatialWeights) { - if (sw.weight()->bandwidth() == 0.0) isGlobal = true; + if (sw.weight().bandwidth() == 0.0) isGlobal = true; } } if (isGlobal) @@ -766,12 +766,12 @@ double GTDRBandwidthOptimizer::criterion_function(const gsl_vector* bws, void* p { Parameter* p = static_cast(params); GTDR* instance = p->instance; - const vector& bandwidths = *(p->bandwidths); + const vector>& bandwidths = p->bandwidths; double nFeature = double(p->featureCount); for (size_t m = 0; m < bandwidths.size(); m++) { double pbw = abs(gsl_vector_get(bws, m)); - bandwidths[m]->setBandwidth(pbw * nFeature); + bandwidths[m].get().setBandwidth(pbw * nFeature); } return instance->bandwidthCriterion(bandwidths); } @@ -784,11 +784,11 @@ const int GTDRBandwidthOptimizer::optimize(GTDR* instance, uword featureCount, s gsl_vector* steps = gsl_vector_alloc(nDim); for (size_t m = 0; m < nDim; m++) { - double target_value = mBandwidths[m]->adaptive() ? mBandwidths[m]->bandwidth() / double(featureCount) : mBandwidths[m]->bandwidth(); + double target_value = mBandwidths[m].get().adaptive() ? mBandwidths[m].get().bandwidth() / double(featureCount) : mBandwidths[m].get().bandwidth(); gsl_vector_set(targets, m, target_value); gsl_vector_set(steps, m, step); } - Parameter params = { instance, &mBandwidths, featureCount }; + Parameter params = { instance, mBandwidths, featureCount }; gsl_multimin_function function = { criterion_function, nDim, ¶ms }; int status = gsl_multimin_fminimizer_set(minimizer, &function, targets, steps); if (status == GSL_SUCCESS) @@ -829,7 +829,7 @@ const int GTDRBandwidthOptimizer::optimize(GTDR* instance, uword featureCount, s { double pbw = abs(gsl_vector_get(minimizer->x, m)); // pbw = (pbw > 1.0 ? 1.0 : pbw); - mBandwidths[m]->setBandwidth(round(pbw * featureCount)); + mBandwidths[m].get().setBandwidth(round(pbw * featureCount)); } } gsl_multimin_fminimizer_free(minimizer); diff --git a/src/gwmodelpp/GTWR.cpp b/src/gwmodelpp/GTWR.cpp index 779beb1d..5cbf1a0b 100644 --- a/src/gwmodelpp/GTWR.cpp +++ b/src/gwmodelpp/GTWR.cpp @@ -35,16 +35,24 @@ mat GTWR::fit() if(mIsAutoselectLambdaBw){ GWM_LOG_STAGE("Lambda and bandwidth optimization") - BandwidthWeight *bw0 = mSpatialWeight.weight(); - mStdistance = mSpatialWeight.distance(); + BandwidthWeight& bw0 = mSpatialWeight.weight(); + //要优化的可变带宽此前被归一化了 + if (bw0.adaptive()) + { + bw0.setBandwidth(bw0.bandwidth() * nDp); + } + else + { + bw0.setBandwidth(bw0.bandwidth() * stDistance().maxDistance()); + } // double lambda0 = 0.05; // double first_bw= bw0->adaptive() ? nDp*0.618 : 0.0; // bw0->setBandwidth(first_bw); vec optim = vec(2, fill::zeros); optim = lambdaBwAutoSelection(bw0, 1000, 1e-3); - mStdistance->setLambda(optim(0)); - bw0->setBandwidth(optim(1)); + stDistance().setLambda(optim(0)); + bw0.setBandwidth(optim(1)); //不能再进行后面的优化 mIsAutoselectBandwidth=false; mIsAutoselectLambda=false; @@ -53,16 +61,15 @@ mat GTWR::fit() if (mIsAutoselectBandwidth) { GWM_LOG_STAGE("Bandwidth optimization") - BandwidthWeight *bw0 = mSpatialWeight.weight(); - double lower = bw0->adaptive() ? 20 : 0.0; - double upper = bw0->adaptive() ? nDp : mSpatialWeight.distance()->maxDistance(); + BandwidthWeight& bw0 = mSpatialWeight.weight(); + double lower = bw0.adaptive() ? 20 : 0.0; + double upper = bw0.adaptive() ? nDp : mSpatialWeight.distance()->maxDistance(); GWM_LOG_INFO(IBandwidthSelectable::infoBandwidthCriterion(bw0)); BandwidthSelector selector(bw0, lower, upper); - BandwidthWeight *bw = selector.optimize(this); - if (bw) + if (selector.optimize(this) == Status::Success) { - mSpatialWeight.setWeight(bw); + mSpatialWeight.setWeight(selector.result()); mBandwidthSelectionCriterionList = selector.bandwidthCriterion(); } GWM_LOG_STOP_RETURN(mStatus, mat(nDp, nVars, arma::fill::zeros)); @@ -71,12 +78,11 @@ mat GTWR::fit() if (mIsAutoselectLambda) { GWM_LOG_STAGE("Lambda optimization") - BandwidthWeight *bw = mSpatialWeight.weight(); - mStdistance = mSpatialWeight.distance(); + BandwidthWeight& bw = mSpatialWeight.weight(); GWM_LOG_INFO(infoLambdaCriterion()); double lambda = lambdaAutoSelection(bw); - mStdistance->setLambda(lambda); + stDistance().setLambda(lambda); GWM_LOG_STOP_RETURN(mStatus, mat(nDp, nVars, arma::fill::zeros)); } @@ -119,7 +125,6 @@ void GTWR::createPredictionDistanceParameter(const arma::mat& locations) { mSpatialWeight.distance()->makeParameter({ mCoords, mCoords, vTimes, vTimes }); } - mStdistance = mSpatialWeight.distance(); } void GTWR::createDistanceParameter() @@ -128,7 +133,6 @@ void GTWR::createDistanceParameter() { mSpatialWeight.distance()->makeParameter({ mCoords, mCoords, vTimes, vTimes }); } - mStdistance = mSpatialWeight.distance(); } @@ -198,7 +202,7 @@ mat GTWR::fitSerial(const mat& x, const vec& y, mat& betasSE, vec& shat, vec& qD return betas.t(); } -double GTWR::bandwidthSizeCriterionCVSerial(BandwidthWeight* bandwidthWeight) +double GTWR::bandwidthSizeCriterionCVSerial(const unique_ptr& bandwidthWeight) { uword nDp = mCoords.n_rows; vec shat(2, fill::zeros); @@ -234,7 +238,7 @@ double GTWR::bandwidthSizeCriterionCVSerial(BandwidthWeight* bandwidthWeight) else return DBL_MAX; } -double GTWR::bandwidthSizeCriterionAICSerial(BandwidthWeight* bandwidthWeight) +double GTWR::bandwidthSizeCriterionAICSerial(const unique_ptr& bandwidthWeight) { uword nDp = mCoords.n_rows, nVar = mX.n_cols; mat betas(nVar, nDp, fill::zeros); @@ -287,12 +291,12 @@ bool GTWR::isValid() { if (GWRBase::isValid()) { - double bw = mSpatialWeight.weight()->bandwidth(); + double bw = mSpatialWeight.weight().bandwidth(); if (!(bw > 0)) { return false; } - double lambda=mStdistance->lambda(); + double lambda = stDistance().lambda(); if (lambda < 0 || lambda > 1) { return false; @@ -395,7 +399,7 @@ mat GTWR::fitOmp(const mat& x, const vec& y, mat& betasSE, vec& shat, vec& qDiag } -double GTWR::bandwidthSizeCriterionCVOmp(BandwidthWeight* bandwidthWeight) +double GTWR::bandwidthSizeCriterionCVOmp(const unique_ptr& bandwidthWeight) { uword nDp = mCoords.n_rows; vec shat(2, fill::zeros); @@ -441,7 +445,7 @@ double GTWR::bandwidthSizeCriterionCVOmp(BandwidthWeight* bandwidthWeight) else return DBL_MAX; } -double GTWR::bandwidthSizeCriterionAICOmp(BandwidthWeight* bandwidthWeight) +double GTWR::bandwidthSizeCriterionAICOmp(const unique_ptr& bandwidthWeight) { uword nDp = mCoords.n_rows, nVar = mX.n_cols; mat betas(nVar, nDp, fill::zeros); @@ -516,20 +520,20 @@ void GTWR::setParallelType(const ParallelType& type) } } -Status GTWR::r_squareByLambda(BandwidthWeight* bandwidthWeight, double lambda, double& rsquare) +Status GTWR::r_squareByLambda(const BandwidthWeight& bandwidthWeight, double lambda, double& rsquare) { // (void)(params); double r2; uword nDp = mCoords.n_rows, nVar = mX.n_cols; mat betas(nVar, nDp, fill::zeros); - mStdistance->setLambda(lambda); - mStdistance->makeParameter({ mCoords, mCoords, vTimes, vTimes }); + stDistance().setLambda(lambda); + stDistance().makeParameter({ mCoords, mCoords, vTimes, vTimes }); for (uword i = 0; i < nDp; i++) { GWM_LOG_STOP_BREAK(mStatus); - mat d = mStdistance->distance(i); + mat d = stDistance().distance(i); // vec w = mSpatialWeight.weightVector(i); - vec w = bandwidthWeight->weight(d); + vec w = bandwidthWeight.weight(d); mat xtw = trans(mX.each_col() % w); mat xtwx = xtw * mX; mat xtwy = xtw * mY; @@ -560,7 +564,7 @@ Status GTWR::r_squareByLambda(BandwidthWeight* bandwidthWeight, double lambda, d return mStatus; } -double GTWR::lambdaAutoSelection(BandwidthWeight* bw) +double GTWR::lambdaAutoSelection(const BandwidthWeight& bw) { // int status; // int iter = 0, max_iter = 1000; @@ -628,25 +632,19 @@ double GTWR::lambdaAutoSelection(BandwidthWeight* bw) else return 0.0; } -double GTWR::criterionByLambdaBw(BandwidthWeight *bandwidth, double lambda, BandwidthSelectionCriterionType criterion) +double GTWR::criterionByLambdaBw(const BandwidthWeight& bandwidth, double lambda, BandwidthSelectionCriterionType criterion) { uword nDp = mCoords.n_rows, nVar = mX.n_cols; mat betas(nVar, nDp, fill::zeros); vec shat(2, fill::zeros); double value = 0.0; - mStdistance->setLambda(lambda); - mStdistance->makeParameter({mCoords, mCoords, vTimes, vTimes}); - //要优化的可变带宽此前被归一化了 - if(bandwidth->adaptive()){ - bandwidth->setBandwidth(bandwidth->bandwidth() * nDp); - }else{ - bandwidth->setBandwidth(bandwidth->bandwidth() * mStdistance->maxDistance()); - } + stDistance().setLambda(lambda); + stDistance().makeParameter({mCoords, mCoords, vTimes, vTimes}); for (uword i = 0; i < nDp; i++) { GWM_LOG_STOP_BREAK(mStatus); vec d = mSpatialWeight.distance()->distance(i); - vec w = bandwidth->weight(d); + vec w = bandwidth.weight(d); if (criterion == BandwidthSelectionCriterionType::CV) { w(i) = 0.0; @@ -725,7 +723,7 @@ double GTWR::criterion_function (const gsl_vector *target, void *params) // 获取参数指针 GTWR* instance = p->instance; - BandwidthWeight* bandwidth = p->bandwidth; + BandwidthWeight& bandwidth = p->bandwidth; // double lambda = p->lambda; BandwidthSelectionCriterionType criterionType=instance->mBandwidthSelectionCriterion; @@ -735,30 +733,26 @@ double GTWR::criterion_function (const gsl_vector *target, void *params) //问题:如果优化的时候reset lambda,设置的值不在0-1范围里,怎么办 // instance->mStdistance->setLambda(lambda_value);//这里和后面计算的里面重复了 - bandwidth->setBandwidth(bandwidth_value); + bandwidth.setBandwidth(bandwidth_value); return instance->criterionByLambdaBw(bandwidth, lambda_value, criterionType); } -vec GTWR::lambdaBwAutoSelection(BandwidthWeight* bandwidth, size_t max_iter, double min_step) +vec GTWR::lambdaBwAutoSelection(BandwidthWeight& bandwidth, size_t max_iter, double min_step) { vec optim(2, fill::zeros); uword nDp = mCoords.n_rows; gsl_multimin_fminimizer *minimizer = gsl_multimin_fminimizer_alloc(gsl_multimin_fminimizer_nmsimplex2rand, 2); gsl_vector* lambda_bw = gsl_vector_alloc(2); gsl_vector* steps = gsl_vector_alloc(2); - gsl_vector_set(lambda_bw, 0, this->mStdistance->lambda()); + gsl_vector_set(lambda_bw, 0, stDistance().lambda()); //带宽近似映射到了0-1 // gsl_vector_set(lambda_bw, 1, bandwidth->adaptive() ? 0.618 : bandwidth->bandwidth()); - double mdis=mStdistance->maxDistance(); - gsl_vector_set(lambda_bw, 1, bandwidth->adaptive() ? bandwidth->bandwidth() / double(nDp) : bandwidth->bandwidth() / mdis); + double mdis = stDistance().maxDistance(); + gsl_vector_set(lambda_bw, 1, bandwidth.adaptive() ? bandwidth.bandwidth() / double(nDp) : bandwidth.bandwidth() / mdis); // gsl_vector_set(lambda_bw, 1, bandwidth->bandwidth()); gsl_vector_set_all(steps, min_step); - GTWR::Parameter params; - params.instance = this; // GTWR类的实例是当前对象 - params.bandwidth = bandwidth; - params.lambda = this->mStdistance->lambda(); - + GTWR::Parameter params { this, bandwidth, stDistance().lambda() }; // gsl_multimin_function minex_func; gsl_multimin_function minex_func = { criterion_function, 2, ¶ms }; @@ -802,7 +796,7 @@ vec GTWR::lambdaBwAutoSelection(BandwidthWeight* bandwidth, size_t max_iter, dou // sDebug << size; // params.instance->debug(sDebug.str(), __FUNCTION__, __FILE__); // #endif - double optbw=bandwidth->adaptive() ? abs(gsl_vector_get(minimizer->x, 1)) * nDp : abs(gsl_vector_get(minimizer->x, 1)) * mdis; + double optbw = bandwidth.adaptive() ? abs(gsl_vector_get(minimizer->x, 1)) * nDp : abs(gsl_vector_get(minimizer->x, 1)) * mdis; cout<<"optimezed lambda:"<< abs(gsl_vector_get(minimizer->x, 0))<x, 0)); diff --git a/src/gwmodelpp/GWCorrelation.cpp b/src/gwmodelpp/GWCorrelation.cpp index d3dcb0bf..beb233ed 100644 --- a/src/gwmodelpp/GWCorrelation.cpp +++ b/src/gwmodelpp/GWCorrelation.cpp @@ -59,17 +59,17 @@ bool GWCorrelation::isValid() for (size_t i = 0; i < nCol; i++) { - BandwidthWeight* bw = mSpatialWeights[i].weight(); + const BandwidthWeight& bw = mSpatialWeights[i].weight(); if (mBandwidthInitilize[i] == GWCorrelation::Specified || mBandwidthInitilize[i] == GWCorrelation::Initial) { - if (bw->adaptive()) + if (bw.adaptive()) { - if (bw->bandwidth() < 1) + if (bw.bandwidth() < 1) return false; } else { - if (bw->bandwidth() < 0.0) + if (bw.bandwidth() < 0.0) return false; } } @@ -103,17 +103,16 @@ void GWCorrelation::run() mXi = mX.col(i/nRsp); mYi = mY.col((i+nRsp)%nRsp); GWM_LOG_INFO(string(GWM_LOG_TAG_GWCORR_INITIAL_BW) + to_string(i)); - BandwidthWeight* bw0 = bandwidth(i); - BandwidthSelector selector; - selector.setBandwidth(bw0); - selector.setLower(bw0->adaptive() ? 20 : 0.0); - selector.setUpper(bw0->adaptive() ? nDp : mSpatialWeights[i].distance()->maxDistance()); - BandwidthWeight* bw = selector.optimize(this); - if(bw) + const BandwidthWeight& bw0 = bandwidth(i); + BandwidthSelector selector(bw0); + selector.setLower(bw0.adaptive() ? 20 : 0.0); + selector.setUpper(bw0.adaptive() ? nDp : mSpatialWeights[i].distance()->maxDistance()); + const BandwidthWeight& bw = selector.result(); + if(selector.optimize(this) == Status::Success) { mSpatialWeights[i].setWeight(bw); } - GWM_LOG_INFO(string(GWM_LOG_TAG_GWCORR_INITIAL_BW) + to_string(i) + "," + to_string(bw->bandwidth())); + GWM_LOG_INFO(string(GWM_LOG_TAG_GWCORR_INITIAL_BW) + to_string(i) + "," + to_string(bw.bandwidth())); } GWM_LOG_STOP_RETURN(mStatus, void()); } @@ -257,7 +256,7 @@ void GWCorrelation::GWCorrelationOmp() } #endif -double GWCorrelation::bandwidthSizeCriterionAICSerial(BandwidthWeight *bandwidthWeight) +double GWCorrelation::bandwidthSizeCriterionAICSerial(const unique_ptr& bandwidthWeight) { int var = mBandwidthSelectionCurrentIndex; uword nDp = mCoords.n_rows; @@ -297,7 +296,7 @@ double GWCorrelation::bandwidthSizeCriterionAICSerial(BandwidthWeight *bandwidth } -double GWCorrelation::bandwidthSizeCriterionCVSerial(BandwidthWeight *bandwidthWeight) +double GWCorrelation::bandwidthSizeCriterionCVSerial(const unique_ptr& bandwidthWeight) { int var = mBandwidthSelectionCurrentIndex; uword nDp = mCoords.n_rows; @@ -335,7 +334,7 @@ double GWCorrelation::bandwidthSizeCriterionCVSerial(BandwidthWeight *bandwidthW } #ifdef ENABLE_OPENMP -double GWCorrelation::bandwidthSizeCriterionAICOmp(BandwidthWeight *bandwidthWeight) +double GWCorrelation::bandwidthSizeCriterionAICOmp(const unique_ptr& bandwidthWeight) { int var = mBandwidthSelectionCurrentIndex; uword nDp = mCoords.n_rows; @@ -392,7 +391,7 @@ double GWCorrelation::bandwidthSizeCriterionAICOmp(BandwidthWeight *bandwidthWei #endif #ifdef ENABLE_OPENMP -double GWCorrelation::bandwidthSizeCriterionCVOmp(BandwidthWeight *bandwidthWeight) +double GWCorrelation::bandwidthSizeCriterionCVOmp(const unique_ptr& bandwidthWeight) { int var = mBandwidthSelectionCurrentIndex; uword nDp = mCoords.n_rows; diff --git a/src/gwmodelpp/GWRBasic.cpp b/src/gwmodelpp/GWRBasic.cpp index 8985f853..52946e3f 100644 --- a/src/gwmodelpp/GWRBasic.cpp +++ b/src/gwmodelpp/GWRBasic.cpp @@ -137,16 +137,15 @@ mat GWRBasic::fit() if (mIsAutoselectBandwidth) { GWM_LOG_STAGE("Bandwidth selection"); - BandwidthWeight* bw0 = mSpatialWeight.weight(); - double lower = mGoldenLowerBounds.value_or(bw0->adaptive() ? 20 : 0.0); - double upper = mGoldenUpperBounds.value_or(bw0->adaptive() ? nDp : mSpatialWeight.distance()->maxDistance()); + const BandwidthWeight& bw0 = mSpatialWeight.weight(); + double lower = mGoldenLowerBounds.value_or(bw0.adaptive() ? 20 : 0.0); + double upper = mGoldenUpperBounds.value_or(bw0.adaptive() ? nDp : mSpatialWeight.distance()->maxDistance()); GWM_LOG_INFO(IBandwidthSelectable::infoBandwidthCriterion(bw0)); - BandwidthSelector selector(bw0, lower, upper); - BandwidthWeight* bw = selector.optimize(this); - if (bw) + BandwidthSelector selector { bw0, lower, upper }; + if (selector.optimize(this) == Status::Success) { - mSpatialWeight.setWeight(bw); + mSpatialWeight.setWeight(selector.result()); #ifdef ENABLE_CUDA if (mParallelType & ParallelType::CUDA) { @@ -345,9 +344,9 @@ mat GWRBasic::fitCoreSHatSerial(const mat& x, const vec& y, const SpatialWeight& return betas.t(); } -double GWRBasic::bandwidthSizeCriterionCV(BandwidthWeight* bandwidthWeight) +double GWRBasic::bandwidthSizeCriterionCV(const unique_ptr& bandwidthWeight) { - SpatialWeight sw(bandwidthWeight, mSpatialWeight.distance()); + SpatialWeight sw(bandwidthWeight->clone(), mSpatialWeight.distance()); try { mat betas = (this->*mFitCoreCVFunction)(mX, mY, sw); @@ -355,7 +354,7 @@ double GWRBasic::bandwidthSizeCriterionCV(BandwidthWeight* bandwidthWeight) double cv = sum(res % res); if (mStatus == Status::Success && isfinite(cv)) { - GWM_LOG_INFO(IBandwidthSelectable::infoBandwidthCriterion(bandwidthWeight, cv)); + GWM_LOG_INFO(IBandwidthSelectable::infoBandwidthCriterion(bandwidthWeight.get(), cv)); GWM_LOG_PROGRESS_PERCENT(exp(- abs(mBandwidthLastCriterion - cv))); mBandwidthLastCriterion = cv; return cv; @@ -369,9 +368,9 @@ double GWRBasic::bandwidthSizeCriterionCV(BandwidthWeight* bandwidthWeight) } -double GWRBasic::bandwidthSizeCriterionAIC(BandwidthWeight* bandwidthWeight) +double GWRBasic::bandwidthSizeCriterionAIC(const unique_ptr& bandwidthWeight) { - SpatialWeight sw(bandwidthWeight, mSpatialWeight.distance()); + SpatialWeight sw(bandwidthWeight->clone(), mSpatialWeight.distance()); try { vec shat; @@ -379,7 +378,7 @@ double GWRBasic::bandwidthSizeCriterionAIC(BandwidthWeight* bandwidthWeight) double value = GWRBase::AICc(mX, mY, betas, shat); if (mStatus == Status::Success && isfinite(value)) { - GWM_LOG_INFO(IBandwidthSelectable::infoBandwidthCriterion(bandwidthWeight, value)); + GWM_LOG_INFO(IBandwidthSelectable::infoBandwidthCriterion(bandwidthWeight.get(), value)); GWM_LOG_PROGRESS_PERCENT(exp(- abs(mBandwidthLastCriterion - value))); mBandwidthLastCriterion = value; return value; @@ -396,7 +395,7 @@ double gwm::GWRBasic::indepVarsSelectionCriterion(const vector& indepVar { mat x = mX.cols(VariableForwardSelector::index2uvec(indepVars, mHasIntercept)); SpatialWeight sw = mSpatialWeight; - sw.weight()->setBandwidth(DBL_MAX); + sw.weight().setBandwidth(DBL_MAX); try { vec shat; @@ -861,7 +860,7 @@ GWM_MPI_WORKER_END return aic; } -double GWRBasic::bandwidthSizeCriterionCVMpi(BandwidthWeight* bandwidthWeight) +double GWRBasic::bandwidthSizeCriterionCVMpi(const unique_ptr& bandwidthWeight) { uword nDp = mX.n_rows, nVar = mX.n_cols; SpatialWeight sw(bandwidthWeight, mSpatialWeight.distance()); @@ -888,7 +887,7 @@ GWM_MPI_WORKER_END return cv; } -double GWRBasic::bandwidthSizeCriterionAICMpi(BandwidthWeight* bandwidthWeight) +double GWRBasic::bandwidthSizeCriterionAICMpi(const unique_ptr& bandwidthWeight) { SpatialWeight sw(bandwidthWeight, mSpatialWeight.distance()); double aic; @@ -1124,7 +1123,7 @@ bool GWRBasic::isValid() { if (GWRBase::isValid()) { - double bw = mSpatialWeight.weight()->bandwidth(); + double bw = mSpatialWeight.weight().bandwidth(); if (!(bw > 0)) { return false; diff --git a/src/gwmodelpp/GWRGeneralized.cpp b/src/gwmodelpp/GWRGeneralized.cpp index 1b95a860..a3f1037d 100644 --- a/src/gwmodelpp/GWRGeneralized.cpp +++ b/src/gwmodelpp/GWRGeneralized.cpp @@ -34,14 +34,15 @@ mat GWRGeneralized::fit() GWM_LOG_STAGE("Bandwidth selection"); // emit message(string("Automatically selecting bandwidth ...")); // emit tick(0, 0); - BandwidthWeight *bw0 = mSpatialWeight.weight(); - double lower = bw0->adaptive() ? 20 : 0.0; - double upper = bw0->adaptive() ? nDp : mSpatialWeight.distance()->maxDistance(); + const BandwidthWeight& bw0 = mSpatialWeight.weight(); + double lower = bw0.adaptive() ? 20 : 0.0; + double upper = bw0.adaptive() ? nDp : mSpatialWeight.distance()->maxDistance(); GWM_LOG_INFO(IBandwidthSelectable::infoBandwidthCriterion(bw0)); BandwidthSelector selector(bw0, lower, upper); - BandwidthWeight *bw = selector.optimize(this); - if (bw) + mStatus = selector.optimize(this); + const BandwidthWeight& bw = selector.result(); + if (mStatus == Status::Success) // Check if the optimization was successful { mSpatialWeight.setWeight(bw); mBandwidthSelectionCriterionList = selector.bandwidthCriterion(); @@ -565,7 +566,7 @@ mat GWRGeneralized::fitBinomialSerial(const mat &x, const vec &y) return betas; } -double GWRGeneralized::bandwidthSizeGGWRCriterionCVSerial(BandwidthWeight *bandwidthWeight) +double GWRGeneralized::bandwidthSizeGGWRCriterionCVSerial(const std::unique_ptr& bandwidthWeight) { uword n = mCoords.n_rows; vec cv = vec(n); @@ -612,7 +613,7 @@ double GWRGeneralized::bandwidthSizeGGWRCriterionCVSerial(BandwidthWeight *bandw } #ifdef ENABLE_OPENMP -double GWRGeneralized::bandwidthSizeGGWRCriterionCVOmp(BandwidthWeight *bandwidthWeight) +double GWRGeneralized::bandwidthSizeGGWRCriterionCVOmp(const std::unique_ptr& bandwidthWeight) { uword n = mCoords.n_rows; vec cv = vec(n); @@ -668,7 +669,7 @@ double GWRGeneralized::bandwidthSizeGGWRCriterionCVOmp(BandwidthWeight *bandwidt } #endif -double GWRGeneralized::bandwidthSizeGGWRCriterionAICSerial(BandwidthWeight *bandwidthWeight) +double GWRGeneralized::bandwidthSizeGGWRCriterionAICSerial(const std::unique_ptr& bandwidthWeight) { uword n = mCoords.n_rows; vec cv = vec(n); @@ -709,7 +710,7 @@ double GWRGeneralized::bandwidthSizeGGWRCriterionAICSerial(BandwidthWeight *band } #ifdef ENABLE_OPENMP -double GWRGeneralized::bandwidthSizeGGWRCriterionAICOmp(BandwidthWeight *bandwidthWeight) +double GWRGeneralized::bandwidthSizeGGWRCriterionAICOmp(const std::unique_ptr& bandwidthWeight) { uword n = mCoords.n_rows; vec cv = vec(n); diff --git a/src/gwmodelpp/GWRLocalCollinearity.cpp b/src/gwmodelpp/GWRLocalCollinearity.cpp index 66fc8f99..90b5730c 100644 --- a/src/gwmodelpp/GWRLocalCollinearity.cpp +++ b/src/gwmodelpp/GWRLocalCollinearity.cpp @@ -50,14 +50,15 @@ mat GWRLocalCollinearity::fit() if(mIsAutoselectBandwidth) { GWM_LOG_STAGE("Bandwidth selection"); - BandwidthWeight* bw0 = mSpatialWeight.weight(); - double lower = bw0->adaptive() ? 20 : 0.0; - double upper = bw0->adaptive() ? nDp : mSpatialWeight.distance()->maxDistance(); + const BandwidthWeight& bw0 = mSpatialWeight.weight(); + double lower = bw0.adaptive() ? 20 : 0.0; + double upper = bw0.adaptive() ? nDp : mSpatialWeight.distance()->maxDistance(); GWM_LOG_INFO(IBandwidthSelectable::infoBandwidthCriterion(bw0)); BandwidthSelector selector(bw0, lower, upper); - BandwidthWeight* bw = selector.optimize(this); - if (bw) + mStatus = selector.optimize(this); + const BandwidthWeight& bw = selector.result(); + if (mStatus == Status::Success) { mSpatialWeight.setWeight(bw); mBandwidthSelectionCriterionList = selector.bandwidthCriterion(); @@ -192,7 +193,7 @@ void GWRLocalCollinearity::setParallelType(const ParallelType& type) setBandwidthSelectionCriterion(mBandwidthSelectionCriterion); } -double GWRLocalCollinearity::bandwidthSizeCriterionCVSerial(BandwidthWeight* bandwidthWeight) +double GWRLocalCollinearity::bandwidthSizeCriterionCVSerial(const unique_ptr& bandwidthWeight) { //行数 uword n = mX.n_rows; @@ -259,7 +260,7 @@ double GWRLocalCollinearity::bandwidthSizeCriterionCVSerial(BandwidthWeight* ban } #ifdef ENABLE_OPENMP -double GWRLocalCollinearity::bandwidthSizeCriterionCVOmp(BandwidthWeight* bandwidthWeight) +double GWRLocalCollinearity::bandwidthSizeCriterionCVOmp(const unique_ptr& bandwidthWeight) { //行数 uword n = mX.n_rows; diff --git a/src/gwmodelpp/GWRMultiscale.cpp b/src/gwmodelpp/GWRMultiscale.cpp index 116fc03d..1237b3f1 100644 --- a/src/gwmodelpp/GWRMultiscale.cpp +++ b/src/gwmodelpp/GWRMultiscale.cpp @@ -170,16 +170,16 @@ mat GWRMultiscale::fit() mBandwidthSizeCriterion = bandwidthSizeCriterionVar(mBandwidthSelectionApproach[i]); mBandwidthSelectionCurrentIndex = i; mXi = mX.col(i); - BandwidthWeight* bw0 = bandwidth(i); - bool adaptive = bw0->adaptive(); + const BandwidthWeight& bw0 = bandwidth(i); + bool adaptive = bw0.adaptive(); GWM_LOG_INFO(string(GWM_LOG_TAG_MGWR_INITIAL_BW) + to_string(i)); - BandwidthSelector selector; - selector.setBandwidth(bw0); + BandwidthSelector selector(bw0); selector.setLower(mGoldenLowerBounds.value_or(adaptive ? mAdaptiveLower : mMinDistances[i])); selector.setUpper(mGoldenUpperBounds.value_or(adaptive ? mCoords.n_rows : mMaxDistances[i])); - BandwidthWeight* bw = selector.optimize(this); - if (bw) + mStatus = selector.optimize(this); + const BandwidthWeight& bw = selector.result(); + if (mStatus == Status::Success) { mSpatialWeights[i].setWeight(bw); #ifdef ENABLE_CUDA @@ -187,7 +187,7 @@ mat GWRMultiscale::fit() mSpatialWeights[i].prepareCuda(mGpuId); #endif // ENABLE_CUDA } - GWM_LOG_INFO(string(GWM_LOG_TAG_MGWR_INITIAL_BW) + to_string(i) + "," + to_string(bw->bandwidth())); + GWM_LOG_INFO(string(GWM_LOG_TAG_MGWR_INITIAL_BW) + to_string(i) + "," + to_string(bw.bandwidth())); } GWM_LOG_STOP_RETURN(mStatus, mat(nDp, nVar, arma::fill::zeros)); } @@ -333,14 +333,14 @@ mat GWRMultiscale::backfitting(const mat& betas0) GWM_LOG_MGWR_BACKFITTING("#variable-bandwidth-selection " + to_string(i)); mBandwidthSizeCriterion = bandwidthSizeCriterionVar(mBandwidthSelectionApproach[i]); mBandwidthSelectionCurrentIndex = i; - BandwidthWeight* bwi0 = bandwidth(i); - bool adaptive = bwi0->adaptive(); - BandwidthSelector selector; - selector.setBandwidth(bwi0); + const BandwidthWeight& bwi0 = bandwidth(i); + bool adaptive = bwi0.adaptive(); + BandwidthSelector selector(bwi0); selector.setLower(mGoldenLowerBounds.value_or(adaptive ? mAdaptiveLower : mMinDistances[i])); selector.setUpper(mGoldenUpperBounds.value_or(adaptive ? mCoords.n_rows : mMaxDistances[i])); - BandwidthWeight* bwi = selector.optimize(this); - double bwi0s = bwi0->bandwidth(), bwi1s = bwi->bandwidth(); + mStatus = selector.optimize(this); + const BandwidthWeight& bwi = selector.result(); + double bwi0s = bwi0.bandwidth(), bwi1s = bwi.bandwidth(); vector vbs_args { to_string(i), to_string(bwi0s), @@ -409,9 +409,9 @@ arma::vec gwm::GWRMultiscale::fitVarBase(const size_t var) return beta; } -double gwm::GWRMultiscale::bandwidthSizeCriterionVarCVBase(BandwidthWeight* bandwidthWeight) +double gwm::GWRMultiscale::bandwidthSizeCriterionVarCVBase(const unique_ptr& bandwidthWeight) { - SpatialWeight sw(bandwidthWeight, mSpatialWeights[mBandwidthSelectionCurrentIndex].distance()); + SpatialWeight sw(bandwidthWeight->clone(), mSpatialWeights[mBandwidthSelectionCurrentIndex].distance()); try { vec betas = (this->*mFitVarCoreCV)(mXi, mYi, sw); @@ -419,7 +419,7 @@ double gwm::GWRMultiscale::bandwidthSizeCriterionVarCVBase(BandwidthWeight* band double cv = sum(res % res); if (mStatus == Status::Success && isfinite(cv)) { - GWM_LOG_INFO(IBandwidthSelectable::infoBandwidthCriterion(bandwidthWeight, cv)); + GWM_LOG_INFO(IBandwidthSelectable::infoBandwidthCriterion(bandwidthWeight.get(), cv)); GWM_LOG_PROGRESS_PERCENT(exp(- abs(mBandwidthLastCriterion - cv))); mBandwidthLastCriterion = cv; return cv; @@ -432,9 +432,9 @@ double gwm::GWRMultiscale::bandwidthSizeCriterionVarCVBase(BandwidthWeight* band } } -double gwm::GWRMultiscale::bandwidthSizeCriterionVarAICBase(BandwidthWeight* bandwidthWeight) +double gwm::GWRMultiscale::bandwidthSizeCriterionVarAICBase(const unique_ptr& bandwidthWeight) { - SpatialWeight sw(bandwidthWeight, mSpatialWeights[mBandwidthSelectionCurrentIndex].distance()); + SpatialWeight sw(bandwidthWeight->clone(), mSpatialWeights[mBandwidthSelectionCurrentIndex].distance()); try { vec shat; @@ -442,7 +442,7 @@ double gwm::GWRMultiscale::bandwidthSizeCriterionVarAICBase(BandwidthWeight* ban double value = GWRBase::AICc(mXi, mYi, betas, shat); if (mStatus == Status::Success && isfinite(value)) { - GWM_LOG_INFO(IBandwidthSelectable::infoBandwidthCriterion(bandwidthWeight, value)); + GWM_LOG_INFO(IBandwidthSelectable::infoBandwidthCriterion(bandwidthWeight.get(), value)); GWM_LOG_PROGRESS_PERCENT(exp(- abs(mBandwidthLastCriterion - value))); mBandwidthLastCriterion = value; return value; @@ -479,17 +479,17 @@ bool GWRMultiscale::isValid() for (size_t i = 0; i < nVar; i++) { - BandwidthWeight* bw = mSpatialWeights[i].weight(); + const BandwidthWeight& bw = mSpatialWeights[i].weight(); if (mBandwidthInitilize[i] == GWRMultiscale::Specified || mBandwidthInitilize[i] == GWRMultiscale::Initial) { - if (bw->adaptive()) + if (bw.adaptive()) { - if (bw->bandwidth() <= 1) + if (bw.bandwidth() <= 1) return false; } else { - if (bw->bandwidth() < 0.0) + if (bw.bandwidth() < 0.0) return false; } } @@ -964,7 +964,7 @@ vec GWRMultiscale::fitVarMpi(const size_t var) return beta; } -double GWRMultiscale::bandwidthSizeCriterionVarCVMpi(BandwidthWeight* bandwidthWeight) +double GWRMultiscale::bandwidthSizeCriterionVarCVMpi(const unique_ptr& bandwidthWeight) { SpatialWeight sw(bandwidthWeight, mSpatialWeights[mBandwidthSelectionCurrentIndex].distance()); int status = 1; @@ -1004,7 +1004,7 @@ double GWRMultiscale::bandwidthSizeCriterionVarCVMpi(BandwidthWeight* bandwidthW else return DBL_MAX; } -double GWRMultiscale::bandwidthSizeCriterionVarAICMpi(BandwidthWeight* bandwidthWeight) +double GWRMultiscale::bandwidthSizeCriterionVarAICMpi(const unique_ptr& bandwidthWeight) { SpatialWeight sw(bandwidthWeight, mSpatialWeights[mBandwidthSelectionCurrentIndex].distance()); int status = 1; diff --git a/src/gwmodelpp/GWRRobust.cpp b/src/gwmodelpp/GWRRobust.cpp index dc8c8e1f..a618ce8b 100644 --- a/src/gwmodelpp/GWRRobust.cpp +++ b/src/gwmodelpp/GWRRobust.cpp @@ -62,14 +62,15 @@ mat GWRRobust::fit() if (mIsAutoselectBandwidth) { GWM_LOG_STAGE("Bandwidth selection"); - BandwidthWeight* bw0 = mSpatialWeight.weight(); - double lower = bw0->adaptive() ? 20 : 0.0; - double upper = bw0->adaptive() ? nDp : mSpatialWeight.distance()->maxDistance(); + const BandwidthWeight& bw0 = mSpatialWeight.weight(); + double lower = bw0.adaptive() ? 20 : 0.0; + double upper = bw0.adaptive() ? nDp : mSpatialWeight.distance()->maxDistance(); GWM_LOG_INFO(IBandwidthSelectable::infoBandwidthCriterion(bw0)); BandwidthSelector selector(bw0, lower, upper); - BandwidthWeight* bw = selector.optimize(this); - if (bw) + mStatus = selector.optimize(this); + const BandwidthWeight& bw = selector.result(); + if (mStatus == Status::Success) // Check if the optimization was successful { mSpatialWeight.setWeight(bw); mBandwidthSelectionCriterionList = selector.bandwidthCriterion(); diff --git a/src/gwmodelpp/GWRScalable.cpp b/src/gwmodelpp/GWRScalable.cpp index 00d13257..9d2f5dfa 100644 --- a/src/gwmodelpp/GWRScalable.cpp +++ b/src/gwmodelpp/GWRScalable.cpp @@ -142,8 +142,8 @@ RegressionDiagnostic GWRScalable::CalcDiagnostic(const mat& x, const vec& y, con void GWRScalable::findDataPointNeighbours() { - BandwidthWeight* bandwidth = mDpSpatialWeight.weight(); - uword nDp = mCoords.n_rows, nBw = uword(bandwidth->bandwidth()) < nDp ? uword(bandwidth->bandwidth()) : nDp; + BandwidthWeight& bandwidth = mDpSpatialWeight.weight(); + uword nDp = mCoords.n_rows, nBw = uword(bandwidth.bandwidth()) < nDp ? uword(bandwidth.bandwidth()) : nDp; if (mParameterOptimizeCriterion == BandwidthSelectionCriterionType::CV) { nBw -= 1; @@ -172,10 +172,10 @@ void GWRScalable::findDataPointNeighbours() mat GWRScalable::findNeighbours(const mat& points, umat &nnIndex) { - BandwidthWeight* bandwidth = mSpatialWeight.weight(); + BandwidthWeight& bandwidth = mSpatialWeight.weight(); uword nDp = mCoords.n_rows; uword nRp = points.n_rows; - uword nBw = uword(bandwidth->bandwidth()) < nDp ? uword(bandwidth->bandwidth()) : nDp; + uword nBw = uword(bandwidth.bandwidth()) < nDp ? uword(bandwidth.bandwidth()) : nDp; umat index(nBw, nRp, fill::zeros); mat dists(nBw, nRp, fill::zeros); for (uword i = 0; i < nRp; i++) @@ -302,15 +302,15 @@ mat GWRScalable::predict(const mat& locations) createDistanceParameter(); mDpSpatialWeight = mSpatialWeight; findDataPointNeighbours(); - BandwidthWeight* bandwidth = mSpatialWeight.weight(); - arma::uword nDp = mX.n_rows, nRp = locations.n_rows, nVar = mX.n_rows, nBw = (uword)bandwidth->bandwidth(); + BandwidthWeight& bandwidth = mSpatialWeight.weight(); + arma::uword nDp = mX.n_rows, nRp = locations.n_rows, nVar = mX.n_rows, nBw = (uword)bandwidth.bandwidth(); if (nBw >= nDp) { nBw = nDp - 1; - bandwidth->setBandwidth((double)nBw); + bandwidth.setBandwidth((double)nBw); } double band0 = 0.0; - switch (bandwidth->kernel()) + switch (bandwidth.kernel()) { case BandwidthWeight::KernelFunctionType::Gaussian: band0 = median(mDpNNDists.col(min(50, nBw) - 1)) / sqrt(3); @@ -348,15 +348,15 @@ mat GWRScalable::predictSerial(const mat& locations, const arma::mat &x, const a { mSpatialWeight.distance()->makeParameter({ locations, mCoords }); } - BandwidthWeight* bandwidth = mSpatialWeight.weight(); + BandwidthWeight& bandwidth = mSpatialWeight.weight(); //uword nDp = mCoords.n_rows; uword nRp = locations.n_rows, nVar = mX.n_cols; - uword nBw = (uword)bandwidth->bandwidth(); + uword nBw = (uword)bandwidth.bandwidth(); double band0 = 0.0; mat G0; umat rpNNIndex; mat rpNNDists = findNeighbours(locations, rpNNIndex); - switch (bandwidth->kernel()) + switch (bandwidth.kernel()) { case BandwidthWeight::KernelFunctionType::Gaussian: band0 = median(rpNNDists.col(min(50, nBw) - 1)) / sqrt(3); @@ -466,15 +466,15 @@ mat GWRScalable::fit() createDistanceParameter(); mDpSpatialWeight = mSpatialWeight; findDataPointNeighbours(); - BandwidthWeight* bandwidth = mSpatialWeight.weight(); - arma::uword nDp = mX.n_rows, nVar = mX.n_cols, nBw = (uword)bandwidth->bandwidth(); + BandwidthWeight& bandwidth = mSpatialWeight.weight(); + arma::uword nDp = mX.n_rows, nVar = mX.n_cols, nBw = (uword)bandwidth.bandwidth(); if (nBw >= nDp) { nBw = nDp - 1; - bandwidth->setBandwidth((double)nBw); + bandwidth.setBandwidth((double)nBw); } double band0 = 0.0; - switch (bandwidth->kernel()) + switch (bandwidth.kernel()) { case BandwidthWeight::KernelFunctionType::Gaussian: band0 = median(mDpNNDists.col(min(50, nBw) - 1)) / sqrt(3); @@ -519,13 +519,13 @@ mat GWRScalable::fit() arma::mat GWRScalable::fitSerial(const arma::mat &x, const arma::vec &y) { - BandwidthWeight* bandwidth = mSpatialWeight.weight(); - uword bw = (uword)bandwidth->bandwidth(); + BandwidthWeight& bandwidth = mSpatialWeight.weight(); + uword bw = (uword)bandwidth.bandwidth(); uword n = x.n_rows, k = x.n_cols, poly1 = mPolynomial + 1; if (bw >= n) { bw = bw - 1; - bandwidth->setBandwidth((double)bw); + bandwidth.setBandwidth((double)bw); } double b = mScale, a = mPenalty; mat XtX = x.t() * x, XtY = x.t() * y; @@ -534,7 +534,7 @@ arma::mat GWRScalable::fitSerial(const arma::mat &x, const arma::vec &y) double band0 = 0.0; umat dpNNIndex; mat dpNNDists = findNeighbours(mCoords, dpNNIndex); - switch (bandwidth->kernel()) + switch (bandwidth.kernel()) { case BandwidthWeight::KernelFunctionType::Gaussian: band0 = median(dpNNDists.col(min(50, bw) - 1)) / sqrt(3); @@ -666,11 +666,11 @@ bool GWRScalable::isValid() { if (GWRBase::isValid()) { - BandwidthWeight* bw = mSpatialWeight.weight(); - if (!(bw->kernel() == BandwidthWeight::Gaussian || bw->kernel() == BandwidthWeight::Exponential)) + BandwidthWeight& bw = mSpatialWeight.weight(); + if (!(bw.kernel() == BandwidthWeight::Gaussian || bw.kernel() == BandwidthWeight::Exponential)) return false; - if (!(bw->bandwidth()>0)) + if (!(bw.bandwidth()>0)) { return false; } diff --git a/src/gwmodelpp/spatialweight/BandwidthWeight.cpp b/src/gwmodelpp/spatialweight/BandwidthWeight.cpp index d2ba1e4d..23c51e54 100644 --- a/src/gwmodelpp/spatialweight/BandwidthWeight.cpp +++ b/src/gwmodelpp/spatialweight/BandwidthWeight.cpp @@ -32,7 +32,7 @@ BandwidthWeight::KernelFunction BandwidthWeight::Kernel[] = &BandwidthWeight::BoxcarKernelFunction }; -vec BandwidthWeight::weight(vec dist) +vec BandwidthWeight::weight(vec dist) const { const KernelFunction *kerf = Kernel + mKernel; uword nr = dist.n_elem; diff --git a/src/gwmodelpp/spatialweight/CRSSTDistance.cpp b/src/gwmodelpp/spatialweight/CRSSTDistance.cpp index 2d699708..1580de58 100644 --- a/src/gwmodelpp/spatialweight/CRSSTDistance.cpp +++ b/src/gwmodelpp/spatialweight/CRSSTDistance.cpp @@ -7,7 +7,7 @@ using namespace std; using namespace arma; using namespace gwm; -vec CRSSTDistance::OrthogonalSTDistance(Distance* spatial, gwm::OneDimDistance* temporal, uword focus, double lambda, double angle) +vec CRSSTDistance::OrthogonalSTDistance(const unique_ptr& spatial, const unique_ptr& temporal, uword focus, double lambda, double angle) { (void)angle; vec sdist = spatial->distance(focus); @@ -30,7 +30,7 @@ vec CRSSTDistance::OrthogonalSTDistance(Distance* spatial, gwm::OneDimDistance* // return sqrt(sdist % sdist + lambda * (tdist % tdist)); } -vec CRSSTDistance::ObliqueSTDistance(Distance* spatial, gwm::OneDimDistance* temporal, uword focus, double lambda, double angle) +vec CRSSTDistance::ObliqueSTDistance(const unique_ptr& spatial, const unique_ptr& temporal, uword focus, double lambda, double angle) { vec sdist = spatial->distance(focus); vec tdist; @@ -46,49 +46,6 @@ vec CRSSTDistance::ObliqueSTDistance(Distance* spatial, gwm::OneDimDistance* tem return stdist; } -CRSSTDistance::CRSSTDistance() : - mSpatialDistance(nullptr), - mTemporalDistance(nullptr), - mLambda(0.0), - mAngle(datum::pi / 2.0) -{ - mCalculator = &OrthogonalSTDistance; -} - -CRSSTDistance::CRSSTDistance(Distance* spatialDistance, gwm::OneDimDistance* temporalDistance, double lambda) : - mLambda(lambda), - mAngle(datum::pi / 2.0) -{ - mSpatialDistance = spatialDistance->clone(); - //mSpatialDistance = static_cast(spatialDistance->clone()); - mTemporalDistance = static_cast(temporalDistance->clone()); - mCalculator = &OrthogonalSTDistance; -} - -CRSSTDistance::CRSSTDistance(Distance* spatialDistance, gwm::OneDimDistance* temporalDistance, double lambda, double angle) : - mLambda(lambda), - mAngle(atan(tan(angle))) -{ - mSpatialDistance = spatialDistance->clone(); - //mSpatialDistance = static_cast(spatialDistance->clone()); - mTemporalDistance = static_cast(temporalDistance->clone()); - mCalculator = (abs(mAngle - datum::pi / 2.0) < 1e-15) ? &OrthogonalSTDistance : &ObliqueSTDistance; -} - -CRSSTDistance::CRSSTDistance(const CRSSTDistance &distance) -{ - mAngle=distance.mAngle; - if (distance.mLambda >= 0 && distance.mLambda <= 1){ - mLambda = distance.mLambda; - } - else throw std::runtime_error("The lambda must be in [0,1]."); - // mLambda = distance.mLambda; - mSpatialDistance = distance.mSpatialDistance->clone(); - //mSpatialDistance = static_cast(distance.mSpatialDistance->clone()); - mTemporalDistance = static_cast(distance.mTemporalDistance->clone()); - mCalculator=distance.mCalculator; -} - void CRSSTDistance::makeParameter(initializer_list plist) { if (plist.size() == 4) diff --git a/src/gwmodelpp/spatialweight/SpatialWeight.cpp b/src/gwmodelpp/spatialweight/SpatialWeight.cpp index 03a0f6d0..d7c50f16 100644 --- a/src/gwmodelpp/spatialweight/SpatialWeight.cpp +++ b/src/gwmodelpp/spatialweight/SpatialWeight.cpp @@ -13,8 +13,8 @@ SpatialWeight &SpatialWeight::operator=(SpatialWeight &&spatialWeight) SpatialWeight &SpatialWeight::operator=(const SpatialWeight &spatialWeight) { if (this == &spatialWeight) return *this; - mWeight = std::move(spatialWeight.mWeight->clone()); - mDistance = std::move(spatialWeight.mDistance->clone()); + mWeight = spatialWeight.mWeight->clone(); + mDistance = spatialWeight.mDistance->clone(); return *this; } diff --git a/test/mpi/testGWRBasicMpi.cpp b/test/mpi/testGWRBasicMpi.cpp index 2c440613..1bcac687 100644 --- a/test/mpi/testGWRBasicMpi.cpp +++ b/test/mpi/testGWRBasicMpi.cpp @@ -170,7 +170,7 @@ TEST_CASE("BasicGWR: LondonHP") REQUIRE_NOTHROW(algorithm.fit()); if (iProcess == 0) { - size_t bw = (size_t)algorithm.spatialWeight().weight()->bandwidth(); + size_t bw = (size_t)algorithm.spatialWeight().weight().bandwidth(); size_t bw0 = 67; switch (criterion) { @@ -293,7 +293,7 @@ TEST_CASE("BasicGWR: LondonHP") REQUIRE_THAT(criterions[5].second, Catch::Matchers::WithinAbs(2452.80388934625, 1e-8)); vector selectedVariables = algorithm.selectedVariables(); REQUIRE_THAT(selectedVariables, Catch::Matchers::Equals(vector({1, 3}))); - double bw = algorithm.spatialWeight().weight()->bandwidth(); + double bw = algorithm.spatialWeight().weight().bandwidth(); REQUIRE(bw == 31.0); RegressionDiagnostic diagnostic = algorithm.diagnostic(); REQUIRE_THAT(diagnostic.AIC, Catch::Matchers::WithinAbs(2435.8161441795, 1e-8)); diff --git a/test/mpi/testGWRMultiscaleMpi.cpp b/test/mpi/testGWRMultiscaleMpi.cpp index dc6c4af2..789581d1 100644 --- a/test/mpi/testGWRMultiscaleMpi.cpp +++ b/test/mpi/testGWRMultiscaleMpi.cpp @@ -86,9 +86,9 @@ TEST_CASE("MGWR: basic flow") if (iProcess == 0) { const vector& spatialWeights = algorithm.spatialWeights(); - REQUIRE_THAT(spatialWeights[0].weight()->bandwidth(), Catch::Matchers::WithinAbs(4623.78, 0.1)); - REQUIRE_THAT(spatialWeights[1].weight()->bandwidth(), Catch::Matchers::WithinAbs(12665.70, 0.1)); - REQUIRE_THAT(spatialWeights[2].weight()->bandwidth(), Catch::Matchers::WithinAbs(12665.70, 0.1)); + REQUIRE_THAT(spatialWeights[0].weight().bandwidth(), Catch::Matchers::WithinAbs(4623.78, 0.1)); + REQUIRE_THAT(spatialWeights[1].weight().bandwidth(), Catch::Matchers::WithinAbs(12665.70, 0.1)); + REQUIRE_THAT(spatialWeights[2].weight().bandwidth(), Catch::Matchers::WithinAbs(12665.70, 0.1)); RegressionDiagnostic diagnostic = algorithm.diagnostic(); REQUIRE_THAT(diagnostic.AICc, Catch::Matchers::WithinAbs(2437.09277417389, 1e-6)); @@ -139,9 +139,9 @@ TEST_CASE("MGWR: basic flow") if (iProcess == 0) { const vector& spatialWeights = algorithm.spatialWeights(); - REQUIRE_THAT(spatialWeights[0].weight()->bandwidth(), Catch::Matchers::WithinAbs(45, 0.1)); - REQUIRE_THAT(spatialWeights[1].weight()->bandwidth(), Catch::Matchers::WithinAbs(98, 0.1)); - REQUIRE_THAT(spatialWeights[2].weight()->bandwidth(), Catch::Matchers::WithinAbs(98, 0.1)); + REQUIRE_THAT(spatialWeights[0].weight().bandwidth(), Catch::Matchers::WithinAbs(45, 0.1)); + REQUIRE_THAT(spatialWeights[1].weight().bandwidth(), Catch::Matchers::WithinAbs(98, 0.1)); + REQUIRE_THAT(spatialWeights[2].weight().bandwidth(), Catch::Matchers::WithinAbs(98, 0.1)); RegressionDiagnostic diagnostic = algorithm.diagnostic(); REQUIRE_THAT(diagnostic.AICc, Catch::Matchers::WithinAbs(2437.935218705351, 1e-6)); @@ -188,9 +188,9 @@ TEST_CASE("MGWR: basic flow") if (iProcess == 0) { const vector& spatialWeights = algorithm.spatialWeights(); - REQUIRE(spatialWeights[0].weight()->bandwidth() == 35); - REQUIRE(spatialWeights[1].weight()->bandwidth() == 98); - REQUIRE(spatialWeights[2].weight()->bandwidth() == 98); + REQUIRE(spatialWeights[0].weight().bandwidth() == 35); + REQUIRE(spatialWeights[1].weight().bandwidth() == 98); + REQUIRE(spatialWeights[2].weight().bandwidth() == 98); RegressionDiagnostic diagnostic = algorithm.diagnostic(); REQUIRE_THAT(diagnostic.RSquare, Catch::Matchers::WithinAbs(0.757377391669, 1e-6)); REQUIRE(algorithm.hasIntercept() == true); @@ -237,9 +237,9 @@ TEST_CASE("MGWR: basic flow") if (iProcess == 0) { const vector& spatialWeights = algorithm.spatialWeights(); - REQUIRE(spatialWeights[0].weight()->bandwidth() == 35); - REQUIRE(spatialWeights[1].weight()->bandwidth() == 98); - REQUIRE(spatialWeights[2].weight()->bandwidth() == 98); + REQUIRE(spatialWeights[0].weight().bandwidth() == 35); + REQUIRE(spatialWeights[1].weight().bandwidth() == 98); + REQUIRE(spatialWeights[2].weight().bandwidth() == 98); RegressionDiagnostic diagnostic = algorithm.diagnostic(); REQUIRE_THAT(diagnostic.RSquare, Catch::Matchers::WithinAbs(0.757377391669, 1e-6)); @@ -288,9 +288,9 @@ TEST_CASE("MGWR: basic flow") if (iProcess == 0) { const vector& spatialWeights = algorithm.spatialWeights(); - REQUIRE(spatialWeights[0].weight()->bandwidth() == 52); - REQUIRE(spatialWeights[1].weight()->bandwidth() == 99); - REQUIRE(spatialWeights[2].weight()->bandwidth() == 99); + REQUIRE(spatialWeights[0].weight().bandwidth() == 52); + REQUIRE(spatialWeights[1].weight().bandwidth() == 99); + REQUIRE(spatialWeights[2].weight().bandwidth() == 99); } } } diff --git a/test/testGTDR.cpp b/test/testGTDR.cpp index a2810619..3c3266d1 100644 --- a/test/testGTDR.cpp +++ b/test/testGTDR.cpp @@ -103,8 +103,8 @@ TEST_CASE("GTDR: basic flow") // REQUIRE_NOTHROW(algorithm.fit()); // const vector& spatialWeights = algorithm.spatialWeights(); -// REQUIRE_THAT(spatialWeights[0].weight()->bandwidth(), Catch::Matchers::WithinAbs(80, 1e-12)); -// // REQUIRE_THAT(spatialWeights[1].weight()->bandwidth(), Catch::Matchers::WithinAbs(2550816, 1e-12)); +// REQUIRE_THAT(spatialWeights[0].weight().bandwidth(), Catch::Matchers::WithinAbs(80, 1e-12)); +// // REQUIRE_THAT(spatialWeights[1].weight().bandwidth(), Catch::Matchers::WithinAbs(2550816, 1e-12)); // } TEST_CASE("GTDR: basic flow with bandwidth optimization (AIC)") @@ -139,8 +139,8 @@ TEST_CASE("GTDR: basic flow with bandwidth optimization (AIC)") REQUIRE_NOTHROW(algorithm.fit()); const vector& spatialWeights = algorithm.spatialWeights(); - REQUIRE_THAT(spatialWeights[0].weight()->bandwidth(), Catch::Matchers::WithinAbs(80, 1e-12)); - REQUIRE_THAT(spatialWeights[1].weight()->bandwidth(), Catch::Matchers::WithinAbs(189, 1e-12)); + REQUIRE_THAT(spatialWeights[0].weight().bandwidth(), Catch::Matchers::WithinAbs(80, 1e-12)); + REQUIRE_THAT(spatialWeights[1].weight().bandwidth(), Catch::Matchers::WithinAbs(189, 1e-12)); } TEST_CASE("GTDR: basic flow with independent variable selection") @@ -244,8 +244,8 @@ TEST_CASE("GTDR: basic flow (multithread)") REQUIRE_THAT(selectedVariables, Catch::Matchers::Equals(vector({1, 3}))); const vector& spatialWeights = algorithm.spatialWeights(); - REQUIRE_THAT(spatialWeights[0].weight()->bandwidth(), Catch::Matchers::WithinAbs(81, 1e-12)); - REQUIRE_THAT(spatialWeights[1].weight()->bandwidth(), Catch::Matchers::WithinAbs(142, 1e-12)); + REQUIRE_THAT(spatialWeights[0].weight().bandwidth(), Catch::Matchers::WithinAbs(81, 1e-12)); + REQUIRE_THAT(spatialWeights[1].weight().bandwidth(), Catch::Matchers::WithinAbs(142, 1e-12)); RegressionDiagnostic diagnostic = algorithm.diagnostic(); REQUIRE_THAT(diagnostic.AICc, Catch::Matchers::WithinAbs(2443.390268119515, 1e-6)); @@ -289,8 +289,8 @@ TEST_CASE("GTDR: basic flow (multithread)") // REQUIRE_NOTHROW(algorithm.fit()); // const vector& spatialWeights = algorithm.spatialWeights(); -// REQUIRE_THAT(spatialWeights[0].weight()->bandwidth(), Catch::Matchers::WithinAbs(80, 1e-12)); -// // REQUIRE_THAT(spatialWeights[1].weight()->bandwidth(), Catch::Matchers::WithinAbs(2550816, 1e-12)); +// REQUIRE_THAT(spatialWeights[0].weight().bandwidth(), Catch::Matchers::WithinAbs(80, 1e-12)); +// // REQUIRE_THAT(spatialWeights[1].weight().bandwidth(), Catch::Matchers::WithinAbs(2550816, 1e-12)); // } // #endif diff --git a/test/testGTWR.cpp b/test/testGTWR.cpp index bbdba18e..634187db 100644 --- a/test/testGTWR.cpp +++ b/test/testGTWR.cpp @@ -46,14 +46,14 @@ TEST_CASE("GTWR: londonhp100") //lambda是空间距离的权重 // SECTION(" lambda>1 | serial") { - // CRSSTDistance distance(&sdist, &tdist, 1.5); + // CRSSTDistance distance(sdist, tdist, 1.5); // BandwidthWeight bandwidth(36,true, BandwidthWeight::Gaussian); // SpatialWeight spatial(&bandwidth, &distance); // // REQUIRE_THROWS(algorithm.fit()); // REQUIRE_THROWS(spatial); // } SECTION("adaptive bandwidth 36 | no bandwidth optimization | auto select lambda") { - CRSSTDistance distance(&sdist, &tdist, 1); + CRSSTDistance distance(sdist, tdist, 1); BandwidthWeight bandwidth(36,true, BandwidthWeight::Gaussian); SpatialWeight spatial(&bandwidth, &distance); algorithm.setSpatialWeight(spatial); @@ -70,7 +70,7 @@ TEST_CASE("GTWR: londonhp100") REQUIRE_THAT(diagnostic.RSquareAdjust, Catch::Matchers::WithinAbs(0.65717667452884, 1e-6)); } SECTION("adaptive bandwidth 36 | no bandwidth optimization | lambda=1 | angle=5/2*pi | serial") { - CRSSTDistance distance(&sdist, &tdist, 1, 5 * arma::datum::pi / 2); + CRSSTDistance distance(sdist, tdist, 1, 5 * arma::datum::pi / 2); BandwidthWeight bandwidth(36,true, BandwidthWeight::Gaussian); SpatialWeight spatial(&bandwidth, &distance); algorithm.setSpatialWeight(spatial); @@ -87,7 +87,7 @@ TEST_CASE("GTWR: londonhp100") REQUIRE_THAT(diagnostic.RSquareAdjust, Catch::Matchers::WithinAbs(0.67497534170905, 1e-8)); } SECTION("adaptive bandwidth 36 | no bandwidth optimization | lambda=0.05 | serial") { - CRSSTDistance distance(&sdist, &tdist, 0.05); + CRSSTDistance distance(sdist, tdist, 0.05); BandwidthWeight bandwidth(36,true, BandwidthWeight::Gaussian); SpatialWeight spatial(&bandwidth, &distance); algorithm.setSpatialWeight(spatial); @@ -103,7 +103,7 @@ TEST_CASE("GTWR: londonhp100") REQUIRE_THAT(diagnostic.RSquareAdjust, Catch::Matchers::WithinAbs(0.65696299229674, 1e-8)); } SECTION("fixed bandwidth 5000 | no bandwidth optimization | lambda=1 | serial") { - CRSSTDistance distance(&sdist, &tdist, 1); + CRSSTDistance distance(sdist, tdist, 1); BandwidthWeight bandwidth(5000,false, BandwidthWeight::Gaussian); SpatialWeight spatial(&bandwidth, &distance); algorithm.setSpatialWeight(spatial); @@ -119,7 +119,7 @@ TEST_CASE("GTWR: londonhp100") REQUIRE_THAT(diagnostic.RSquareAdjust, Catch::Matchers::WithinAbs(0.67369159445212 , 1e-8)); } SECTION("fixed bandwidth 5000 | no bandwidth optimization | lambda=0.05 | serial") { - CRSSTDistance distance(&sdist, &tdist, 0.05); + CRSSTDistance distance(sdist, tdist, 0.05); BandwidthWeight bandwidth(5000,false, BandwidthWeight::Gaussian); SpatialWeight spatial(&bandwidth, &distance); algorithm.setSpatialWeight(spatial); @@ -135,32 +135,32 @@ TEST_CASE("GTWR: londonhp100") REQUIRE_THAT(diagnostic.RSquareAdjust, Catch::Matchers::WithinAbs(0.66131126771988, 1e-8)); } SECTION("fixed bandwidth | CV Gaussian bandwidth optimization | lambda=1 ") { - CRSSTDistance distance(&sdist, &tdist, 1); + CRSSTDistance distance(sdist, tdist, 1); BandwidthWeight bandwidth(0, false, BandwidthWeight::Gaussian); SpatialWeight spatial(&bandwidth, &distance); algorithm.setSpatialWeight(spatial); algorithm.setIsAutoselectBandwidth(true); algorithm.setBandwidthSelectionCriterion(GTWR::BandwidthSelectionCriterionType::CV); REQUIRE_NOTHROW(algorithm.fit()); - size_t bw = (size_t)algorithm.spatialWeight().weight()->bandwidth(); + size_t bw = (size_t)algorithm.spatialWeight().weight().bandwidth(); REQUIRE(bw == 5076); } SECTION("adaptive bandwidth | AICc Bisquare bandwidth optimization | lambda=0.05 ") { - CRSSTDistance distance(&sdist, &tdist, 0.05); + CRSSTDistance distance(sdist, tdist, 0.05); BandwidthWeight bandwidth(0, true, BandwidthWeight::Bisquare); SpatialWeight spatial(&bandwidth, &distance); algorithm.setSpatialWeight(spatial); algorithm.setIsAutoselectBandwidth(true); algorithm.setBandwidthSelectionCriterion(GTWR::BandwidthSelectionCriterionType::AIC); REQUIRE_NOTHROW(algorithm.fit()); - size_t bw = (size_t)algorithm.spatialWeight().weight()->bandwidth(); + size_t bw = (size_t)algorithm.spatialWeight().weight().bandwidth(); REQUIRE(bw == 70); } SECTION("prediction |adaptive bandwidth 36 | no optimization | lambda=0.05 | serial") { mat londonhp100_coord_predict = londonhp100_coord * 1.1; // londonhp100_coord.head_rows(5).print("origin"); // londonhp100_coord_predict.head_rows(5).print("zoom"); - CRSSTDistance distance(&sdist, &tdist, 0.05); + CRSSTDistance distance(sdist, tdist, 0.05); BandwidthWeight bandwidth(36,true, BandwidthWeight::Gaussian); SpatialWeight spatial(&bandwidth, &distance); algorithm.setSpatialWeight(spatial); @@ -175,7 +175,7 @@ TEST_CASE("GTWR: londonhp100") } SECTION("adaptive bandwidth: from 60 to optimize | lambda bandwidth optimization") { - CRSSTDistance distance(&sdist, &tdist, 0.05); + CRSSTDistance distance(sdist, tdist, 0.05); BandwidthWeight bandwidth(60,true, BandwidthWeight::Gaussian); SpatialWeight spatial(&bandwidth, &distance); algorithm.setSpatialWeight(spatial); @@ -185,7 +185,7 @@ TEST_CASE("GTWR: londonhp100") REQUIRE_NOTHROW(algorithm.fit()); RegressionDiagnostic diagnostic = algorithm.diagnostic(); REQUIRE(algorithm.hasIntercept() == true); - size_t bw = (size_t)algorithm.spatialWeight().weight()->bandwidth(); + size_t bw = (size_t)algorithm.spatialWeight().weight().bandwidth(); // REQUIRE(bw == 46); // REQUIRE_THAT(algorithm.getLambda(), Catch::Matchers::WithinAbs(0.0905251641, 1e-6)); // REQUIRE_THAT(diagnostic.AIC, Catch::Matchers::WithinAbs(2443.4941325699, 1e-8)); @@ -196,7 +196,7 @@ TEST_CASE("GTWR: londonhp100") #ifdef ENABLE_OPENMP SECTION("adaptive bandwidth | CV bandwidth optimization | lambda=0.05 | omp parallel ") { - CRSSTDistance distance(&sdist, &tdist, 0.05); + CRSSTDistance distance(sdist, tdist, 0.05); BandwidthWeight bandwidth(0, true, BandwidthWeight::Gaussian); SpatialWeight spatial(&bandwidth, &distance); algorithm.setSpatialWeight(spatial); @@ -208,7 +208,7 @@ TEST_CASE("GTWR: londonhp100") REQUIRE_NOTHROW(algorithm.fit()); RegressionDiagnostic diagnostic = algorithm.diagnostic(); REQUIRE(algorithm.hasIntercept() == true); - size_t bw = (size_t)algorithm.spatialWeight().weight()->bandwidth(); + size_t bw = (size_t)algorithm.spatialWeight().weight().bandwidth(); REQUIRE(bw == 46); REQUIRE_THAT(diagnostic.AIC, Catch::Matchers::WithinAbs(2443.5498915432, 1e-8)); REQUIRE_THAT(diagnostic.AICc, Catch::Matchers::WithinAbs(2453.2551390127, 1e-8)); @@ -216,7 +216,7 @@ TEST_CASE("GTWR: londonhp100") REQUIRE_THAT(diagnostic.RSquareAdjust, Catch::Matchers::WithinAbs(0.6551810065492, 1e-8)); } SECTION("adaptive bandwidth | no bandwidth optimization | lambda=0.5 | omp parallel ") { - CRSSTDistance distance(&sdist, &tdist, 0.5); + CRSSTDistance distance(sdist, tdist, 0.5); BandwidthWeight bandwidth(46, true, BandwidthWeight::Gaussian); SpatialWeight spatial(&bandwidth, &distance); algorithm.setSpatialWeight(spatial); @@ -253,7 +253,7 @@ TEST_CASE("GTWR: cancel") CRSDistance sdist(false); OneDimDistance tdist; - CRSSTDistance distance(&sdist, &tdist, 1); + CRSSTDistance distance(sdist, tdist, 1); BandwidthWeight bandwidth(36,true, BandwidthWeight::Gaussian); SpatialWeight spatial(&bandwidth, &distance); diff --git a/test/testGWCorrelation.cpp b/test/testGWCorrelation.cpp index 5c570b7f..e269b706 100644 --- a/test/testGWCorrelation.cpp +++ b/test/testGWCorrelation.cpp @@ -116,9 +116,9 @@ TEST_CASE("GWCorrelation: londonhp100") REQUIRE_NOTHROW(algorithm.run()); const vector& spatialWeights = algorithm.spatialWeights(); - REQUIRE_THAT(spatialWeights[0].weight()->bandwidth(), Catch::Matchers::WithinAbs(68, 1e-3)); - REQUIRE_THAT(spatialWeights[1].weight()->bandwidth(), Catch::Matchers::WithinAbs(26, 1e-3)); - REQUIRE_THAT(spatialWeights[2].weight()->bandwidth(), Catch::Matchers::WithinAbs(98, 1e-3)); + REQUIRE_THAT(spatialWeights[0].weight().bandwidth(), Catch::Matchers::WithinAbs(68, 1e-3)); + REQUIRE_THAT(spatialWeights[1].weight().bandwidth(), Catch::Matchers::WithinAbs(26, 1e-3)); + REQUIRE_THAT(spatialWeights[2].weight().bandwidth(), Catch::Matchers::WithinAbs(98, 1e-3)); vec p = {0.0, 0.25, 0.5, 0.75, 1.0}; mat localcorr_q0 = { @@ -163,9 +163,9 @@ TEST_CASE("GWCorrelation: londonhp100") REQUIRE_NOTHROW(algorithm.run()); const vector& spatialWeights = algorithm.spatialWeights(); - REQUIRE_THAT(spatialWeights[0].weight()->bandwidth(), Catch::Matchers::WithinAbs(68, 1e-3)); - REQUIRE_THAT(spatialWeights[1].weight()->bandwidth(), Catch::Matchers::WithinAbs(26, 1e-3)); - REQUIRE_THAT(spatialWeights[2].weight()->bandwidth(), Catch::Matchers::WithinAbs(98, 1e-3)); + REQUIRE_THAT(spatialWeights[0].weight().bandwidth(), Catch::Matchers::WithinAbs(68, 1e-3)); + REQUIRE_THAT(spatialWeights[1].weight().bandwidth(), Catch::Matchers::WithinAbs(26, 1e-3)); + REQUIRE_THAT(spatialWeights[2].weight().bandwidth(), Catch::Matchers::WithinAbs(98, 1e-3)); vec p = {0.0, 0.25, 0.5, 0.75, 1.0}; diff --git a/test/testGWRBasic.cpp b/test/testGWRBasic.cpp index b1e76f0a..5963fd17 100644 --- a/test/testGWRBasic.cpp +++ b/test/testGWRBasic.cpp @@ -143,7 +143,7 @@ TEST_CASE("BasicGWR: LondonHP") } #endif // ENABLE_CUDA REQUIRE_NOTHROW(algorithm.fit()); - size_t bw = (size_t)algorithm.spatialWeight().weight()->bandwidth(); + size_t bw = (size_t)algorithm.spatialWeight().weight().bandwidth(); size_t bw0 = 67; switch (criterion) { @@ -250,7 +250,7 @@ TEST_CASE("BasicGWR: LondonHP") REQUIRE_THAT(criterions[5].second, Catch::Matchers::WithinAbs(2452.80388934625, 1e-8)); vector selectedVariables = algorithm.selectedVariables(); REQUIRE_THAT(selectedVariables, Catch::Matchers::Equals(vector({1, 3}))); - double bw = algorithm.spatialWeight().weight()->bandwidth(); + double bw = algorithm.spatialWeight().weight().bandwidth(); REQUIRE(bw == 31.0); RegressionDiagnostic diagnostic = algorithm.diagnostic(); REQUIRE_THAT(diagnostic.AIC, Catch::Matchers::WithinAbs(2435.8161441795, 1e-8)); diff --git a/test/testGWRGeneralized.cpp b/test/testGWRGeneralized.cpp index 8a40e69a..670a7e66 100644 --- a/test/testGWRGeneralized.cpp +++ b/test/testGWRGeneralized.cpp @@ -81,7 +81,7 @@ TEST_CASE("GGWR: adaptive bandwidth autoselection of with AIC") REQUIRE_NOTHROW(algorithm.fit()); - size_t bw = (size_t)algorithm.spatialWeight().weight()->bandwidth(); + size_t bw = (size_t)algorithm.spatialWeight().weight().bandwidth(); REQUIRE(bw == 21); GWRGeneralizedDiagnostic diagnostic = algorithm.getDiagnostic(); @@ -119,7 +119,7 @@ TEST_CASE("GGWR: adaptive bandwidth autoselection and with binomial") REQUIRE_NOTHROW(algorithm.fit()); - size_t bw = (size_t)algorithm.spatialWeight().weight()->bandwidth(); + size_t bw = (size_t)algorithm.spatialWeight().weight().bandwidth(); REQUIRE(bw == 275); REQUIRE_NOTHROW(algorithm.fit()); @@ -162,7 +162,7 @@ TEST_CASE("GGWR: multithread basic flow") algorithm.setFamily(GWRGeneralized::Family::Poisson); REQUIRE_NOTHROW(algorithm.fit()); - double bw = algorithm.spatialWeight().weight()->bandwidth(); + double bw = algorithm.spatialWeight().weight().bandwidth(); REQUIRE(bw == 27.0); GWRGeneralizedDiagnostic diagnostic = algorithm.getDiagnostic(); diff --git a/test/testGWRLocalCollinearity.cpp b/test/testGWRLocalCollinearity.cpp index 906ba178..26562fc0 100644 --- a/test/testGWRLocalCollinearity.cpp +++ b/test/testGWRLocalCollinearity.cpp @@ -78,7 +78,7 @@ TEST_CASE("LocalCollinearityGWR") REQUIRE_NOTHROW(algorithm.fit()); - size_t bw = (size_t)algorithm.spatialWeight().weight()->bandwidth(); + size_t bw = (size_t)algorithm.spatialWeight().weight().bandwidth(); REQUIRE(bw == 67); } @@ -157,7 +157,7 @@ TEST_CASE("LocalCollinearityGWR") algorithm.setOmpThreadNum(omp_get_num_threads()); REQUIRE_NOTHROW(algorithm.fit()); - double bw = algorithm.spatialWeight().weight()->bandwidth(); + double bw = algorithm.spatialWeight().weight().bandwidth(); REQUIRE(bw == 67.0); REQUIRE_THAT(algorithm.localCN().max(), Catch::Matchers::WithinAbs(50.634464389348, 1e-8)); diff --git a/test/testGWRMultiscale.cpp b/test/testGWRMultiscale.cpp index 6d519464..a0fb00ca 100644 --- a/test/testGWRMultiscale.cpp +++ b/test/testGWRMultiscale.cpp @@ -79,9 +79,9 @@ TEST_CASE("MGWR: basic flow") REQUIRE_NOTHROW(algorithm.fit()); const vector& spatialWeights = algorithm.spatialWeights(); - REQUIRE_THAT(spatialWeights[0].weight()->bandwidth(), Catch::Matchers::WithinAbs(4623.78, 0.1)); - REQUIRE_THAT(spatialWeights[1].weight()->bandwidth(), Catch::Matchers::WithinAbs(12665.70, 0.1)); - REQUIRE_THAT(spatialWeights[2].weight()->bandwidth(), Catch::Matchers::WithinAbs(12665.70, 0.1)); + REQUIRE_THAT(spatialWeights[0].weight().bandwidth(), Catch::Matchers::WithinAbs(4623.78, 0.1)); + REQUIRE_THAT(spatialWeights[1].weight().bandwidth(), Catch::Matchers::WithinAbs(12665.70, 0.1)); + REQUIRE_THAT(spatialWeights[2].weight().bandwidth(), Catch::Matchers::WithinAbs(12665.70, 0.1)); RegressionDiagnostic diagnostic = algorithm.diagnostic(); REQUIRE_THAT(diagnostic.AICc, Catch::Matchers::WithinAbs(2437.09277417389, 1e-6)); @@ -126,9 +126,9 @@ TEST_CASE("MGWR: basic flow") REQUIRE_NOTHROW(algorithm.fit()); const vector& spatialWeights = algorithm.spatialWeights(); - REQUIRE_THAT(spatialWeights[0].weight()->bandwidth(), Catch::Matchers::WithinAbs(45, 0.1)); - REQUIRE_THAT(spatialWeights[1].weight()->bandwidth(), Catch::Matchers::WithinAbs(98, 0.1)); - REQUIRE_THAT(spatialWeights[2].weight()->bandwidth(), Catch::Matchers::WithinAbs(98, 0.1)); + REQUIRE_THAT(spatialWeights[0].weight().bandwidth(), Catch::Matchers::WithinAbs(45, 0.1)); + REQUIRE_THAT(spatialWeights[1].weight().bandwidth(), Catch::Matchers::WithinAbs(98, 0.1)); + REQUIRE_THAT(spatialWeights[2].weight().bandwidth(), Catch::Matchers::WithinAbs(98, 0.1)); RegressionDiagnostic diagnostic = algorithm.diagnostic(); REQUIRE_THAT(diagnostic.AICc, Catch::Matchers::WithinAbs(2437.935218705351, 1e-6)); @@ -168,9 +168,9 @@ TEST_CASE("MGWR: basic flow") algorithm.setParallelType(parallel); REQUIRE_NOTHROW(algorithm.fit()); const vector& spatialWeights = algorithm.spatialWeights(); - REQUIRE(spatialWeights[0].weight()->bandwidth() == 35); - REQUIRE(spatialWeights[1].weight()->bandwidth() == 98); - REQUIRE(spatialWeights[2].weight()->bandwidth() == 98); + REQUIRE(spatialWeights[0].weight().bandwidth() == 35); + REQUIRE(spatialWeights[1].weight().bandwidth() == 98); + REQUIRE(spatialWeights[2].weight().bandwidth() == 98); RegressionDiagnostic diagnostic = algorithm.diagnostic(); REQUIRE_THAT(diagnostic.RSquare, Catch::Matchers::WithinAbs(0.757377391669, 1e-6)); REQUIRE(algorithm.hasIntercept() == true); @@ -211,9 +211,9 @@ TEST_CASE("MGWR: basic flow") REQUIRE_NOTHROW(algorithm.fit()); const vector& spatialWeights = algorithm.spatialWeights(); - REQUIRE(spatialWeights[0].weight()->bandwidth() == 35); - REQUIRE(spatialWeights[1].weight()->bandwidth() == 98); - REQUIRE(spatialWeights[2].weight()->bandwidth() == 98); + REQUIRE(spatialWeights[0].weight().bandwidth() == 35); + REQUIRE(spatialWeights[1].weight().bandwidth() == 98); + REQUIRE(spatialWeights[2].weight().bandwidth() == 98); RegressionDiagnostic diagnostic = algorithm.diagnostic(); REQUIRE_THAT(diagnostic.AICc, Catch::Matchers::WithinAbs(2438.256543496552, 1e-6)); @@ -255,9 +255,9 @@ TEST_CASE("MGWR: basic flow") REQUIRE_NOTHROW(algorithm.fit()); const vector& spatialWeights = algorithm.spatialWeights(); - REQUIRE(spatialWeights[0].weight()->bandwidth() == 52); - REQUIRE(spatialWeights[1].weight()->bandwidth() == 99); - REQUIRE(spatialWeights[2].weight()->bandwidth() == 99); + REQUIRE(spatialWeights[0].weight().bandwidth() == 52); + REQUIRE(spatialWeights[1].weight().bandwidth() == 99); + REQUIRE(spatialWeights[2].weight().bandwidth() == 99); } } diff --git a/test/testGWRRobust.cpp b/test/testGWRRobust.cpp index 939fa15f..668c3530 100644 --- a/test/testGWRRobust.cpp +++ b/test/testGWRRobust.cpp @@ -123,7 +123,7 @@ TEST_CASE("RobustGWR: adaptive bandwidth autoselection of with CV") REQUIRE_NOTHROW(algorithm.fit()); - size_t bw = (size_t)algorithm.spatialWeight().weight()->bandwidth(); + size_t bw = (size_t)algorithm.spatialWeight().weight().bandwidth(); REQUIRE(bw == 67); /* RegressionDiagnostic diagnostic = algorithm.diagnostic(); @@ -232,7 +232,7 @@ TEST_CASE("RobustGWR: multithread basic flow") vector selectedVariables = algorithm.selectedVariables(); REQUIRE_THAT(selectedVariables, Catch::Matchers::Equals(vector({1, 3}))); - double bw = algorithm.spatialWeight().weight()->bandwidth(); + double bw = algorithm.spatialWeight().weight().bandwidth(); REQUIRE(bw == 31.0); /* RegressionDiagnostic diagnostic = algorithm.diagnostic(); From 3e26e8c500f4961c50ba4112f637647f99beb8c8 Mon Sep 17 00:00:00 2001 From: HPDell Date: Wed, 23 Jul 2025 23:11:20 +0100 Subject: [PATCH 3/5] fix: GTWR angle set --- include/gwmodelpp/spatialweight/CRSSTDistance.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/gwmodelpp/spatialweight/CRSSTDistance.h b/include/gwmodelpp/spatialweight/CRSSTDistance.h index 02a5e264..cb0e15be 100644 --- a/include/gwmodelpp/spatialweight/CRSSTDistance.h +++ b/include/gwmodelpp/spatialweight/CRSSTDistance.h @@ -82,7 +82,7 @@ class CRSSTDistance : public Distance explicit CRSSTDistance(const Distance& spatialDistance, const OneDimDistance& temporalDistance, double lambda, double angle): CRSSTDistance(spatialDistance, temporalDistance, lambda) { - mAngle = angle, + mAngle = atan(tan(angle)), mCalculator = (abs(mAngle - arma::datum::pi / 2.0) < 1e-15) ? &OrthogonalSTDistance : &ObliqueSTDistance; } @@ -97,7 +97,7 @@ class CRSSTDistance : public Distance explicit CRSSTDistance(Distance&& spatialDistance, OneDimDistance&& temporalDistance, double lambda, double angle): CRSSTDistance(spatialDistance, temporalDistance, lambda) { - mAngle = angle, + mAngle = atan(tan(angle)), mCalculator = (abs(mAngle - arma::datum::pi / 2.0) < 1e-15) ? &OrthogonalSTDistance : &ObliqueSTDistance; } @@ -112,7 +112,7 @@ class CRSSTDistance : public Distance explicit CRSSTDistance(const std::unique_ptr& spatialDistance, const std::unique_ptr& temporalDistance, double lambda, double angle): CRSSTDistance(spatialDistance, temporalDistance, lambda) { - mAngle = angle, + mAngle = atan(tan(angle)), mCalculator = (abs(mAngle - arma::datum::pi / 2.0) < 1e-15) ? &OrthogonalSTDistance : &ObliqueSTDistance; } @@ -127,7 +127,7 @@ class CRSSTDistance : public Distance explicit CRSSTDistance(std::unique_ptr&& spatialDistance, std::unique_ptr&& temporalDistance, double lambda, double angle): CRSSTDistance(std::move(spatialDistance), std::move(temporalDistance), lambda) { - mAngle = angle, + mAngle = atan(tan(angle)), mCalculator = (abs(mAngle - arma::datum::pi / 2.0) < 1e-15) ? &OrthogonalSTDistance : &ObliqueSTDistance; } From d515c5ef7a8b12f0b0e546500d4abf7b90c1f173 Mon Sep 17 00:00:00 2001 From: HPDell Date: Tue, 12 Aug 2025 17:02:37 +0100 Subject: [PATCH 4/5] edit: docs --- .../gwmodelpp/spatialweight/SpatialWeight.h | 227 ++++++++++-------- 1 file changed, 124 insertions(+), 103 deletions(-) diff --git a/include/gwmodelpp/spatialweight/SpatialWeight.h b/include/gwmodelpp/spatialweight/SpatialWeight.h index 4698cabf..b56c1599 100644 --- a/include/gwmodelpp/spatialweight/SpatialWeight.h +++ b/include/gwmodelpp/spatialweight/SpatialWeight.h @@ -23,9 +23,9 @@ namespace gwm /** * \~english * @brief A combined class of distance and weight. - * Instances of this class are usually constructed by providing pointers to CGwmDistance and CGwmWeight. - * In the construct function, instances of types CGwmDistance and CGwmWeight will be cloned. - * This class provide the method CGwmSpatialWeight::weightVector() to calculate spatial weight directly. + * Instances of this class are usually constructed by providing pointers to Distance and Weight. + * In the construct function, instances of types Distance and Weight will be cloned. + * This class provide the method SpatialWeight::weightVector() to calculate spatial weight directly. * * If the distance and weight are set by pointers, this class will take the control of them, * and when destructing the pointers will be deleted. @@ -33,9 +33,9 @@ namespace gwm * * \~chinese * @brief 距离和权重的组合类。 - * 该类的实例通常用于提供指向 CGwmDistance 和 CGwmWeight 类型的指针。 - * 在构造函数中,类型 CGwmDistance 和 CGwmWeight 的实例将会被克隆。 - * 该类型也提供方法 CGwmSpatialWeight::weightVector() 用于直接计算空间权重。 + * 该类的实例通常用于提供指向 Distance 和 Weight 类型的指针。 + * 在构造函数中,类型 Distance 和 Weight 的实例将会被克隆。 + * 该类型也提供方法 SpatialWeight::weightVector() 用于直接计算空间权重。 * * 如果距离和权重通过指针设置,那么该类对象将会取得他们的控制权,并在析构的时候释放资源。 * 如果距离和权重通过引用设置,那么该类对象将会克隆他们。 @@ -49,22 +49,22 @@ class SpatialWeight /** * \~english - * @brief Construct a new CGwmSpatialWeight object. + * @brief Construct a new SpatialWeight object. * * \~chinese - * @brief 构造一个新的 CGwmSpatialWeight 对象。 + * @brief 构造一个新的 SpatialWeight 对象。 */ SpatialWeight() {} /** * \~english - * @brief Construct a new CGwmSpatialWeight object. + * @brief Construct a new SpatialWeight object. * * @param weight Pointer to a weight configuration. * @param distance Pointer to distance configuration. * * \~chinese - * @brief 构造一个新的 CGwmSpatialWeight 对象。 + * @brief 构造一个新的 SpatialWeight 对象。 * * @param weight 指向权重配置的指针。 * @param distance 指向距离配置的指针。 @@ -76,13 +76,13 @@ class SpatialWeight /** * \~english - * @brief Construct a new CGwmSpatialWeight object. + * @brief Construct a new SpatialWeight object. * * @param weight Pointer to a weight configuration. * @param distance Pointer to distance configuration. * * \~chinese - * @brief 构造一个新的 CGwmSpatialWeight 对象。 + * @brief 构造一个新的 SpatialWeight 对象。 * * @param weight 指向权重配置的指针。 * @param distance 指向距离配置的指针。 @@ -94,13 +94,13 @@ class SpatialWeight /** * \~english - * @brief Construct a new CGwmSpatialWeight object. + * @brief Construct a new SpatialWeight object. * * @param weight Pointer to a weight configuration. * @param distance Pointer to distance configuration. * * \~chinese - * @brief 构造一个新的 CGwmSpatialWeight 对象。 + * @brief 构造一个新的 SpatialWeight 对象。 * * @param weight 指向权重配置的指针。 * @param distance 指向距离配置的指针。 @@ -111,13 +111,13 @@ class SpatialWeight {} /** - * @brief Construct a new CGwmSpatialWeight object. + * @brief Construct a new SpatialWeight object. * * @param weight Reference to a weight configuration. * @param distance Reference to distance configuration. * * \~chinese - * @brief 构造一个新的 CGwmSpatialWeight 对象。 + * @brief 构造一个新的 SpatialWeight 对象。 * * @param weight 指向权重配置的引用。 * @param distance 指向距离配置的引用。 @@ -129,12 +129,12 @@ class SpatialWeight /** * \~english - * @brief Copy construct a new CGwmSpatialWeight object. + * @brief Copy construct a new SpatialWeight object. * * @param spatialWeight Reference to the object to copy from. * * \~chinese - * @brief 复制构造一个新的 CGwmSpatialWeight 对象。 + * @brief 复制构造一个新的 SpatialWeight 对象。 * * @param spatialWeight 被复制对象的引用。 */ @@ -144,12 +144,12 @@ class SpatialWeight {} /** - * @brief Move construct a new CGwmSpatialWeight object. + * @brief Move construct a new SpatialWeight object. * * @param other Reference to the object to move from. * * \~chinese - * @brief 移动构造一个新的 CGwmSpatialWeight 对象。 + * @brief 移动构造一个新的 SpatialWeight 对象。 * * @param other 被移动对象的引用。 */ @@ -160,23 +160,23 @@ class SpatialWeight /** * \~english - * @brief Destroy the CGwmSpatialWeight object. + * @brief Destroy the SpatialWeight object. * * \~chinese - * @brief 销毁 CGwmSpatialWeight 对象。 + * @brief 销毁 SpatialWeight 对象。 */ virtual ~SpatialWeight() {}; /** * \~english - * @brief Get the pointer to CGwmSpatialWeight::mWeight . + * @brief Get the pointer to SpatialWeight::mWeight . * - * @return Pointer to CGwmSpatialWeight::mWeight . + * @return Pointer to SpatialWeight::mWeight . * * \~chinese - * @brief 获得 CGwmSpatialWeight::mWeight 的指针。 + * @brief 获得 SpatialWeight::mWeight 的指针。 * - * @return 指针 CGwmSpatialWeight::mWeight 。 + * @return 指针 SpatialWeight::mWeight 。 */ const std::unique_ptr& weight() const { @@ -185,15 +185,15 @@ class SpatialWeight /** * \~english - * @brief Set the pointer to CGwmSpatialWeight::mWeight object. + * @brief Set the pointer to SpatialWeight::mWeight object. * - * @param weight Pointer to CGwmWeight instance. + * @param weight Pointer to Weight instance. * Control of this pointer will be taken, and it will be deleted when destructing. * * \~chinese - * @brief 设置 CGwmSpatialWeight::mWeight 指针所指向的对象。 + * @brief 设置 SpatialWeight::mWeight 指针所指向的对象。 * - * @param weight 指向 CGwmWeight 实例的指针。 + * @param weight 指向 Weight 实例的指针。 * 获取该指针的控制权,并在类对象析构时释放该指针所指向的对象。 */ void setWeight(const Weight *weight) @@ -206,15 +206,15 @@ class SpatialWeight /** * \~english - * @brief Set the pointer to CGwmSpatialWeight::mWeight object. + * @brief Set the pointer to SpatialWeight::mWeight object. * - * @param weight Reference to CGwmWeight instance. + * @param weight Reference to Weight instance. * This object will be cloned. * * \~chinese - * @brief 设置 CGwmSpatialWeight::mWeight 指针所指向的对象。 + * @brief 设置 SpatialWeight::mWeight 指针所指向的对象。 * - * @param weight 指向 CGwmWeight 实例的指针。 + * @param weight 指向 Weight 实例的指针。 * 指针所指向的对象会被克隆。 */ void setWeight(const Weight& weight) @@ -224,15 +224,15 @@ class SpatialWeight /** * \~english - * @brief Set the pointer to CGwmSpatialWeight::mWeight object. + * @brief Set the pointer to SpatialWeight::mWeight object. * - * @param weight Reference to CGwmWeight instance. + * @param weight Reference to Weight instance. * This object will be cloned. * * \~chinese - * @brief 设置 CGwmSpatialWeight::mWeight 指针所指向的对象。 + * @brief 设置 SpatialWeight::mWeight 指针所指向的对象。 * - * @param weight 指向 CGwmWeight 实例的指针。 + * @param weight 指向 Weight 实例的指针。 * 指针所指向的对象会被克隆。 */ void setWeight(Weight&& weight) @@ -240,6 +240,19 @@ class SpatialWeight mWeight = weight.clone(); } + /** + * \~english + * @brief Set the pointer to SpatialWeight::mWeight object. + * + * @param weight Right reference of unique pointer to Weight instance. + * This object will be moved. + * + * \~chinese + * @brief 设置 SpatialWeight::mWeight 指针所指向的对象。 + * + * @param weight 指向 Weight 实例的专属智能指针的右值引用。 + * 指针所指向的对象会被移动。 + */ void setWeight(std::unique_ptr&& weight) { mWeight = std::move(weight); @@ -247,30 +260,30 @@ class SpatialWeight /** * \~english - * @brief Get the pointer to CGwmSpatialWeight::mWeight and cast it to required type. + * @brief Get the reference of SpatialWeight::mWeight and cast it to required type. * - * @tparam T Type of return value. Only CGwmBandwidthWeight is allowed. - * @return Casted pointer to CGwmSpatialWeight::mWeight. + * @tparam T Type of return value. Only BandwidthWeight is allowed. + * @return Casted reference of SpatialWeight::mWeight. * * \~chinese - * @brief 获得指针 CGwmSpatialWeight::mWeight 并将其转换到所要求的类型 \p T 。 + * @brief 获得 SpatialWeight::mWeight 的引用并将其转换到所要求的类型 \p T 。 * - * @tparam T 返回值的类型。只允许设置为 CGwmWeight 的派生类。 - * @return 转换后的 CGwmSpatialWeight::mWeight 指针。 + * @tparam T 返回值的类型。只允许设置为 Weight 的派生类。 + * @return 转换后的 SpatialWeight::mWeight 引用。 */ template T& weight() const { return nullptr; } /** * \~english - * @brief Get the pointer to CGwmSpatialWeight::mDistance. + * @brief Get the pointer to SpatialWeight::mDistance. * - * @return Pointer to CGwmSpatialWeight::mDistance. + * @return Pointer to SpatialWeight::mDistance. * * \~chinese - * @brief 获得指针 CGwmSpatialWeight::mDistance。 + * @brief 获得指针 SpatialWeight::mDistance。 * - * @return CGwmSpatialWeight::mDistance 指针。 + * @return SpatialWeight::mDistance 指针。 */ const std::unique_ptr& distance() const { @@ -279,15 +292,15 @@ class SpatialWeight /** * \~english - * @brief Set the pointer to CGwmSpatialWeight::mDistance object. + * @brief Set the pointer to SpatialWeight::mDistance object. * - * @param distance Pointer to CGwmDistance instance. + * @param distance Pointer to Distance instance. * Control of this pointer will be taken, and it will be deleted when destructing. * * \~chinese - * @brief 设置 CGwmSpatialWeight::mDistance 指针所指向的对象。 + * @brief 设置 SpatialWeight::mDistance 指针所指向的对象。 * - * @param distance Pointer to CGwmDistance instance. + * @param distance Pointer to Distance instance. * Con获取该指针的控制权,并在类对象析构时释放该指针所指向的对象。 */ void setDistance(const Distance *distance) @@ -300,15 +313,15 @@ class SpatialWeight /** * \~english - * @brief Set the pointer to CGwmSpatialWeight::mDistance object. + * @brief Set the pointer to SpatialWeight::mDistance object. * - * @param distance Reference to CGwmDistance instance. + * @param distance Reference to Distance instance. * This object will be cloned. * * \~chinese - * @brief 设置 CGwmSpatialWeight::mDistance 指针所指向的对象。 + * @brief 设置 SpatialWeight::mDistance 指针所指向的对象。 * - * @param distance 指向 CGwmDistance 实例的指针。 + * @param distance 指向 Distance 实例的指针。 * 指针所指向的对象会被克隆。 */ void setDistance(const Distance& distance) @@ -318,15 +331,15 @@ class SpatialWeight /** * \~english - * @brief Set the pointer to CGwmSpatialWeight::mDistance object. + * @brief Set the pointer to SpatialWeight::mDistance object. * - * @param distance Reference to CGwmDistance instance. + * @param distance Reference to Distance instance. * This object will be cloned. * * \~chinese - * @brief 设置 CGwmSpatialWeight::mDistance 指针所指向的对象。 + * @brief 设置 SpatialWeight::mDistance 指针所指向的对象。 * - * @param distance 指向 CGwmDistance 实例的指针。 + * @param distance 指向 Distance 实例的指针。 * 指针所指向的对象会被克隆。 */ void setDistance(Distance&& distance) @@ -334,11 +347,19 @@ class SpatialWeight mDistance = distance.clone(); } - void setDistance(const std::unique_ptr& distance) - { - mDistance = distance->clone(); - } - + /** + * \~english + * @brief Set the pointer to SpatialWeight::mDistance object. + * + * @param distance Right reference of unique pointer to Distance instance. + * This object will be cloned. + * + * \~chinese + * @brief 设置 SpatialWeight::mDistance 指针所指向的对象。 + * + * @param distance 指向 Distance 实例的专属智能指针的右值引用。 + * 指针所指向的对象会被移动。 + */ void setDistance(std::unique_ptr&& distance) { mDistance = std::move(distance); @@ -346,16 +367,16 @@ class SpatialWeight /** * \~english - * @brief Get the pointer to CGwmSpatialWeight::mDistance and cast it to required type. + * @brief Get the pointer to SpatialWeight::mDistance and cast it to required type. * - * @tparam T Type of return value. Only CGwmCRSDistance and CGwmMinkwoskiDistance is allowed. - * @return Casted pointer to CGwmSpatialWeight::mDistance. + * @tparam T Type of return value. Only CRSDistance and MinkwoskiDistance is allowed. + * @return Casted pointer to SpatialWeight::mDistance. * * \~chinese - * @brief 获得指针 CGwmSpatialWeight::mDistance 并将其转换到所要求的类型 \p T 。 + * @brief 获得指针 SpatialWeight::mDistance 并将其转换到所要求的类型 \p T 。 * - * @tparam T 返回值的类型。只允许设置为 CGwmDistance 的派生类。 - * @return 转换后的 CGwmSpatialWeight::mDistance 指针。 + * @tparam T 返回值的类型。只允许设置为 Distance 的派生类。 + * @return 转换后的 SpatialWeight::mDistance 指针。 */ template T& distance() const { return nullptr; } @@ -365,16 +386,16 @@ class SpatialWeight /** * \~english * @brief Override operator = for this class. - * This function will first delete the current CGwmSpatialWeight::mWeight and CGwmSpatialWeight::mDistance, - * and then clone CGwmWeight and CGwmDistance instances according pointers of the right value. + * This function will first delete the current SpatialWeight::mWeight and SpatialWeight::mDistance, + * and then clone Weight and Distance instances according pointers of the right value. * * @param spatialWeight Reference to the right value. * @return Reference of this object. * * \~chinese * @brief 重载的 \p = 运算符。 - * 该函数会先实方当前 CGwmSpatialWeight::mWeight 和 CGwmSpatialWeight::mDistance 所指向的对象, - * 然后克隆右值传入的 CGwmWeight 和 CGwmDistance 实例。 + * 该函数会先实方当前 SpatialWeight::mWeight 和 SpatialWeight::mDistance 所指向的对象, + * 然后克隆右值传入的 Weight 和 Distance 实例。 * * @param spatialWeight 右值的引用。 * @return 该对象的引用。 @@ -384,16 +405,16 @@ class SpatialWeight /** * \~english * @brief Override operator = for this class. - * This function will first delete the current CGwmSpatialWeight::mWeight and CGwmSpatialWeight::mDistance, - * and then clone CGwmWeight and CGwmDistance instances according pointers of the right value. + * This function will first delete the current SpatialWeight::mWeight and SpatialWeight::mDistance, + * and then clone Weight and Distance instances according pointers of the right value. * * @param spatialWeight Right value reference to the right value. * @return Reference of this object. * * \~chinese * @brief 重载的 \p = 运算符。 - * 该函数会先实方当前 CGwmSpatialWeight::mWeight 和 CGwmSpatialWeight::mDistance 所指向的对象, - * 然后克隆右值传入的 CGwmWeight 和 CGwmDistance 实例。 + * 该函数会先实方当前 SpatialWeight::mWeight 和 SpatialWeight::mDistance 所指向的对象, + * 然后克隆右值传入的 Weight 和 Distance 实例。 * * @param spatialWeight 右值的引用。 * @return 该对象的引用。 @@ -483,14 +504,14 @@ class SpatialWeight /** * \~english - * @brief Get the pointer to CGwmSpatialWeight::mWeight and cast it to CGwmBandwidthWeight type. + * @brief Get the pointer to SpatialWeight::mWeight and cast it to BandwidthWeight type. * - * @return Casted pointer to CGwmSpatialWeight::mWeight. + * @return Casted pointer to SpatialWeight::mWeight. * * \~chinese - * @brief 获得指针 CGwmSpatialWeight::mWeight 并将其转换到所要求的类型 CGwmBandwidthWeight 。 + * @brief 获得指针 SpatialWeight::mWeight 并将其转换到所要求的类型 BandwidthWeight 。 * - * @return 转换后的 CGwmSpatialWeight::mWeight 指针。 + * @return 转换后的 SpatialWeight::mWeight 指针。 */ template<> inline BandwidthWeight& SpatialWeight::weight() const @@ -500,14 +521,14 @@ inline BandwidthWeight& SpatialWeight::weight() const /** * \~english - * @brief Get the pointer to CGwmSpatialWeight::mDistance and cast it to CGwmCRSDistance type. + * @brief Get the pointer to SpatialWeight::mDistance and cast it to CRSDistance type. * - * @return Casted pointer to CGwmSpatialWeight::mDistance. + * @return Casted pointer to SpatialWeight::mDistance. * * \~chinese - * @brief 获得指针 CGwmSpatialWeight::mDistance 并将其转换到所要求的类型 CGwmCRSDistance 。 + * @brief 获得指针 SpatialWeight::mDistance 并将其转换到所要求的类型 CRSDistance 。 * - * @return 转换后的 CGwmSpatialWeight::mDistance 指针。 + * @return 转换后的 SpatialWeight::mDistance 指针。 */ template<> inline CRSDistance& SpatialWeight::distance() const @@ -517,14 +538,14 @@ inline CRSDistance& SpatialWeight::distance() const /** * \~english - * @brief Get the pointer to CGwmSpatialWeight::mDistance and cast it to CGwmCRSSTDistance type. + * @brief Get the pointer to SpatialWeight::mDistance and cast it to CRSSTDistance type. * - * @return Casted pointer to CGwmSpatialWeight::mDistance. + * @return Casted pointer to SpatialWeight::mDistance. * * \~chinese - * @brief 获得指针 CGwmSpatialWeight::mDistance 并将其转换到所要求的类型 CGwmCRSSTDistance 。 + * @brief 获得指针 SpatialWeight::mDistance 并将其转换到所要求的类型 CRSSTDistance 。 * - * @return 转换后的 CGwmSpatialWeight::mDistance 指针。 + * @return 转换后的 SpatialWeight::mDistance 指针。 */ template<> inline CRSSTDistance& SpatialWeight::distance() const @@ -534,14 +555,14 @@ inline CRSSTDistance& SpatialWeight::distance() const /** * \~english - * @brief Get the pointer to CGwmSpatialWeight::mDistance and cast it to CGwmMinkwoskiDistance type. + * @brief Get the pointer to SpatialWeight::mDistance and cast it to MinkwoskiDistance type. * - * @return Casted pointer to CGwmSpatialWeight::mDistance. + * @return Casted pointer to SpatialWeight::mDistance. * * \~chinese - * @brief 获得指针 CGwmSpatialWeight::mDistance 并将其转换到所要求的类型 CGwmMinkwoskiDistance 。 + * @brief 获得指针 SpatialWeight::mDistance 并将其转换到所要求的类型 MinkwoskiDistance 。 * - * @return 转换后的 CGwmSpatialWeight::mDistance 指针。 + * @return 转换后的 SpatialWeight::mDistance 指针。 */ template<> inline MinkwoskiDistance& SpatialWeight::distance() const @@ -551,14 +572,14 @@ inline MinkwoskiDistance& SpatialWeight::distance() const /** * \~english - * @brief Get the pointer to CGwmSpatialWeight::mDistance and cast it to CGwmDMatDistance type. + * @brief Get the pointer to SpatialWeight::mDistance and cast it to DMatDistance type. * - * @return Casted pointer to CGwmSpatialWeight::mDistance. + * @return Casted pointer to SpatialWeight::mDistance. * * \~chinese - * @brief 获得指针 CGwmSpatialWeight::mDistance 并将其转换到所要求的类型 CGwmDMatDistance 。 + * @brief 获得指针 SpatialWeight::mDistance 并将其转换到所要求的类型 DMatDistance 。 * - * @return 转换后的 CGwmSpatialWeight::mDistance 指针。 + * @return 转换后的 SpatialWeight::mDistance 指针。 */ template<> inline DMatDistance& SpatialWeight::distance() const @@ -568,14 +589,14 @@ inline DMatDistance& SpatialWeight::distance() const /** * \~english - * @brief Get the pointer to CGwmSpatialWeight::mDistance and cast it to CGwmOneDimDistance type. + * @brief Get the pointer to SpatialWeight::mDistance and cast it to OneDimDistance type. * - * @return Casted pointer to CGwmSpatialWeight::mDistance. + * @return Casted pointer to SpatialWeight::mDistance. * * \~chinese - * @brief 获得指针 CGwmSpatialWeight::mDistance 并将其转换到所要求的类型 CGwmOneDimDistance 。 + * @brief 获得指针 SpatialWeight::mDistance 并将其转换到所要求的类型 OneDimDistance 。 * - * @return 转换后的 CGwmSpatialWeight::mDistance 指针。 + * @return 转换后的 SpatialWeight::mDistance 指针。 */ template<> inline OneDimDistance& SpatialWeight::distance() const From 818d8a23ab2d885187b3ea64d505ca735bb6b430 Mon Sep 17 00:00:00 2001 From: HPDell Date: Tue, 12 Aug 2025 17:14:14 +0100 Subject: [PATCH 5/5] fix: include memory header --- include/gwmodelpp/spatialweight/Weight.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/gwmodelpp/spatialweight/Weight.h b/include/gwmodelpp/spatialweight/Weight.h index 82f2efbc..1d64a35d 100644 --- a/include/gwmodelpp/spatialweight/Weight.h +++ b/include/gwmodelpp/spatialweight/Weight.h @@ -6,6 +6,7 @@ #include "gwmodelpp/spatialweight/cuda/ISpatialCudaEnabled.h" #endif // ENABLE_CUDA +#include #include #include #include "armadillo_config.h"