From 922cdfb100b404d3da2a8a1e45192d8f65b637b4 Mon Sep 17 00:00:00 2001 From: szh <2659007320@qq.com> Date: Tue, 10 Mar 2026 14:25:02 +0800 Subject: [PATCH 1/7] update lcgwr --- src/TaskThread/gwmscalablegwralgorithm.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/TaskThread/gwmscalablegwralgorithm.cpp b/src/TaskThread/gwmscalablegwralgorithm.cpp index 8aa5716..c3aa810 100644 --- a/src/TaskThread/gwmscalablegwralgorithm.cpp +++ b/src/TaskThread/gwmscalablegwralgorithm.cpp @@ -255,8 +255,12 @@ void GwmScalableGWRAlgorithm::run() mBetas = betas; // mDiagnostic = CalcDiagnostic(mY, mX, mBetas, mShat); mDiagnostic0 = mSGWRCore->diagnostic(); - // arma::uword nDp = mX.n_rows; - // double sigmaHat = mDiagnostic0.RSS / (nDp - 2 * trS + trStS); + mShat = mSGWRCore->sHat(); + mBetasSE = mSGWRCore->betasSE(); + mat betasTV = mBetas / mBetasSE; + double trS = mShat(0), trStS = mShat(1); + arma::uword nDp = mX.n_rows; + double sigmaHat = mDiagnostic0.RSS / (nDp - 2 * trS + trStS); vec yhat = sum(mX % mBetas, 1); vec residual = mY - yhat; @@ -264,9 +268,9 @@ void GwmScalableGWRAlgorithm::run() qMakePair(QString("%1"), mBetas), qMakePair(QString("y"), mY), qMakePair(QString("yhat"), yhat), - qMakePair(QString("residual"), residual) - // qMakePair(QString("%1_SE"), mBetasSE), - // qMakePair(QString("%1_TV"), betasTV) + qMakePair(QString("residual"), residual), + qMakePair(QString("%1_SE"), mBetasSE), + qMakePair(QString("%1_TV"), betasTV) }); } else From 2cd56b0a863e654afb4f2014aa8b27a05cab55eb Mon Sep 17 00:00:00 2001 From: szh <2659007320@qq.com> Date: Mon, 20 Apr 2026 15:46:58 +0800 Subject: [PATCH 2/7] sync multithreading GWR implementation --- src/TaskThread/gwmbasicgwralgorithm.cpp | 16 +++++--- src/TaskThread/gwmgeneralizedgwralgorithm.cpp | 26 ++++++------- src/TaskThread/gwmgwpcataskthread.cpp | 38 ++++++++++++++++++- .../gwmlocalcollinearitygwralgorithm.cpp | 9 +++-- 4 files changed, 66 insertions(+), 23 deletions(-) diff --git a/src/TaskThread/gwmbasicgwralgorithm.cpp b/src/TaskThread/gwmbasicgwralgorithm.cpp index 54217f9..e4cb4a3 100644 --- a/src/TaskThread/gwmbasicgwralgorithm.cpp +++ b/src/TaskThread/gwmbasicgwralgorithm.cpp @@ -1,4 +1,4 @@ -#include "gwmbasicgwralgorithm.h" +#include "gwmbasicgwralgorithm.h" #include #include #include @@ -826,6 +826,7 @@ double GwmBasicGWRAlgorithm::bandwidthSizeCriterionAICSerial(GwmBandwidthWeight* double GwmBasicGWRAlgorithm::bandwidthSizeCriterionAICOmp(GwmBandwidthWeight *bandwidthWeight) { int nDp = mDataPoints.n_rows, nVar = mIndepVars.size() + 1; + const int selectorStep = static_cast(mBandwidthSizeSelector.bandwidthCriterion().size()); mat betas(nVar, nDp, fill::zeros); mat shat_all(2, mOmpThreadNum, fill::zeros); bool flag = true; @@ -854,8 +855,10 @@ double GwmBasicGWRAlgorithm::bandwidthSizeCriterionAICOmp(GwmBandwidthWeight *ba { flag = false; } - if(mBandwidthSizeSelector.counter<10) - emit tick(mBandwidthSizeSelector.counter*10 + current * 10 / nDp, 100); + // if(mBandwidthSizeSelector.counter<10) + // emit tick(mBandwidthSizeSelector.counter*10 + current * 10 / nDp, 100); + if (selectorStep < 10) + emit tick(selectorStep * 10 + current * 10 / nDp, 100); current++; } } @@ -976,6 +979,7 @@ double GwmBasicGWRAlgorithm::bandwidthSizeCriterionCVSerial(GwmBandwidthWeight * double GwmBasicGWRAlgorithm::bandwidthSizeCriterionCVOmp(GwmBandwidthWeight *bandwidthWeight) { int nDp = mDataPoints.n_rows; + const int selectorStep = static_cast(mBandwidthSizeSelector.bandwidthCriterion().size()); vec shat(2, fill::zeros); vec cv_all(mOmpThreadNum, fill::zeros); bool flag = true; @@ -1006,8 +1010,10 @@ double GwmBasicGWRAlgorithm::bandwidthSizeCriterionCVOmp(GwmBandwidthWeight *ban { flag = false; } - if(mBandwidthSizeSelector.counter<10) - emit tick(mBandwidthSizeSelector.counter*10 + current * 10 / nDp, 100); + // if(mBandwidthSizeSelector.counter<10) + // emit tick(mBandwidthSizeSelector.counter*10 + current * 10 / nDp, 100); + if (selectorStep < 10) + emit tick(selectorStep * 10 + current * 10 / nDp, 100); current++; } } diff --git a/src/TaskThread/gwmgeneralizedgwralgorithm.cpp b/src/TaskThread/gwmgeneralizedgwralgorithm.cpp index 9f00eb6..00bdb5f 100644 --- a/src/TaskThread/gwmgeneralizedgwralgorithm.cpp +++ b/src/TaskThread/gwmgeneralizedgwralgorithm.cpp @@ -613,7 +613,7 @@ mat GwmGeneralizedGWRAlgorithm::regressionPoissonOmp(const mat &x, const vec &y) mat S(isStoreS ? nDp : 1, nDp, fill::zeros); int current = 0; if(mHasHatMatrix && !checkCanceled()){ - mat shat = mat(2,mOmpThreadNum,fill::zeros); + mat shat = mat(2,mOmpThreadNum,fill::zeros); #pragma omp parallel for num_threads(mOmpThreadNum) for(int i = 0; i < nDp; i++){ mat ci,s_ri; @@ -842,7 +842,7 @@ double GwmGeneralizedGWRAlgorithm::bandwidthSizeGGWRCriterionCVSerial(GwmBandwid .arg(res); emit message(msg); return res; - } + } else return DBL_MAX; } @@ -907,7 +907,7 @@ double GwmGeneralizedGWRAlgorithm::bandwidthSizeGGWRCriterionAICSerial(GwmBandwi int n = mDataPoints.n_rows; vec cv = vec(n); mat S = mat(n,n); - mat wt = mat(n,n); + mat wt = mat(n,n); for (int i = 0; i < n && !checkCanceled(); i++) { vec d = mSpatialWeight.distance()->distance(i); @@ -1484,11 +1484,11 @@ void GwmGeneralizedGWRAlgorithm::fTest(FTestParameters params) f3.append(f3i); continue; } - + double g1 = diagB(0); double g2 = diagB(1); double numdf = g1 * g1 / g2; - + // 检查计算结果的有效性 if (g1 <= 0 || g2 <= 0 || numdf <= 0 || !isfinite(numdf)) { @@ -1500,7 +1500,7 @@ void GwmGeneralizedGWRAlgorithm::fTest(FTestParameters params) f3.append(f3i); continue; } - + GwmFTestResult f3i; f3i.s = (vk2(i) / g1) / sigma2delta1; f3i.df1 = numdf; @@ -1540,20 +1540,20 @@ vec GwmGeneralizedGWRAlgorithm::calcDiagBSerial(int i) arma::uword nDp = mX.n_rows, nVar = mX.n_cols; vec diagB(nDp, fill::zeros), c(nDp, fill::zeros); mat wspan(1, nVar, fill::ones); - + // 第一遍循环:计算 c(所有数据点的系数矩阵第 i 列的平均值) for (arma::uword j = 0; j < nDp && !checkCanceled(); j++) { vec wj = mWtMat2.col(j); vec weights = wj % mWt2; - + // 检查权重有效性 if (sum(weights) < 1e-10 || any(weights < 0) || !weights.is_finite()) { emit error("Invalid weights in calcDiagB (first loop)."); return { DBL_MAX, DBL_MAX }; } - + mat xtw = trans(mX % (weights * wspan)); try { // 使用 inv_sympd 替代 pinv,与 BasicGWR 保持一致 @@ -1564,20 +1564,20 @@ vec GwmGeneralizedGWRAlgorithm::calcDiagBSerial(int i) return { DBL_MAX, DBL_MAX }; } } - + // 第二遍循环:计算 diagB for (arma::uword k = 0; k < nDp && !checkCanceled(); k++) { vec wk = mWtMat2.col(k); vec weights = wk % mWt2; - + // 检查权重有效性 if (sum(weights) < 1e-10 || any(weights < 0) || !weights.is_finite()) { emit error("Invalid weights in calcDiagB (second loop)."); return { DBL_MAX, DBL_MAX }; } - + mat xtw = trans(mX % (weights * wspan)); try { // 使用 inv_sympd 替代 pinv,与 BasicGWR 保持一致 @@ -1589,7 +1589,7 @@ vec GwmGeneralizedGWRAlgorithm::calcDiagBSerial(int i) return { DBL_MAX, DBL_MAX }; } } - + diagB = 1.0 / nDp * diagB; return { sum(diagB), sum(diagB % diagB) }; } diff --git a/src/TaskThread/gwmgwpcataskthread.cpp b/src/TaskThread/gwmgwpcataskthread.cpp index d338bd0..43045a6 100644 --- a/src/TaskThread/gwmgwpcataskthread.cpp +++ b/src/TaskThread/gwmgwpcataskthread.cpp @@ -129,6 +129,14 @@ void GwmGWPCATaskThread::run() if(Robust()) { emit message(QString(tr("Running Robust GWPCA ..."))); + + // Robust scores 需要与 loadings 使用同一份 rwpca(V) 结果, + // 否则可能因为特征向量符号不确定性导致 scores 与旧版不一致。 + if (scoresCal()) + { + mScores = cube(mDataPoints.n_rows, mK, mDataPoints.n_rows, fill::zeros); + } + mLocalPV = robustSolveSerial(mX, mLoadings, mSDev); if(checkCanceled()) @@ -137,6 +145,8 @@ void GwmGWPCATaskThread::run() } mVariance = mSDev % mSDev; + + // Robust 分支在 robustSolveSerial() 内已按需要同步填充 mScores。 } else { @@ -318,6 +328,7 @@ void GwmGWPCATaskThread::initPoints() mDataPoints(i, 0) = centroPoint.x(); mDataPoints(i, 1) = centroPoint.y(); } + } void GwmGWPCATaskThread::initXY(mat &x, const QList &indepVars) @@ -452,6 +463,12 @@ mat GwmGWPCATaskThread::robustSolveSerial(const mat& x, cube& loadings, mat& sde mat d_all(nVar, nDp, fill::zeros); loadings = cube(nDp, nVar, mK, fill::zeros); + // 若外层希望输出 scores,则同时计算,确保与 loadings 使用同一份 V。 + const bool needScores = scoresCal(); + if (needScores && mScores.n_elem == 0) + { + mScores = cube(nDp, mK, nDp, fill::zeros); + } for(int i=0;i(mSelector.bandwidthCriterion().size()); #pragma omp parallel for num_threads(mOmpThreadNum) for (int i = 0; i < n; i++) { @@ -855,8 +887,10 @@ double GwmGWPCATaskThread::bandwidthSizeCriterionCVOmp(GwmBandwidthWeight *weigh V = V * trans(V); score_all(thread) += pow(sum(mX.row(i) - mX.row(i) * V),2); } - if(mSelector.counter<10) - emit tick(mSelector.counter * 10 + current * 10 / n, 100); + // if(mSelector.counter<10) + // emit tick(mSelector.counter * 10 + current * 10 / n, 100); + if (selectorStep < 10) + emit tick(selectorStep * 10 + current * 10 / n, 100); current++; } } diff --git a/src/TaskThread/gwmlocalcollinearitygwralgorithm.cpp b/src/TaskThread/gwmlocalcollinearitygwralgorithm.cpp index 70196d8..cc9365d 100644 --- a/src/TaskThread/gwmlocalcollinearitygwralgorithm.cpp +++ b/src/TaskThread/gwmlocalcollinearitygwralgorithm.cpp @@ -1,4 +1,4 @@ -#include "gwmlocalcollinearitygwralgorithm.h" +#include "gwmlocalcollinearitygwralgorithm.h" #include @@ -326,6 +326,7 @@ double GwmLocalCollinearityGWRAlgorithm::bandwidthSizeCriterionCVOmp(GwmBandwidt mat mXnot1 = mX.cols(1, mX.n_cols - 1); //主循环 int current = 0; + const int selectorStep = static_cast(selector.bandwidthCriterion().size()); #pragma omp parallel for num_threads(mOmpThreadNum) for (int i = 0; i < n; i++) { @@ -359,8 +360,10 @@ double GwmLocalCollinearityGWRAlgorithm::bandwidthSizeCriterionCVOmp(GwmBandwidt } } betas.row(i) = trans( ridgelm(wgt,locallambda(i)) ); - if(selector.counter<10) - emit tick(selector.counter*10 + current * 10 / n, 100); + // if(selector.counter<10) + // emit tick(selector.counter*10 + current * 10 / n, 100); + if (selectorStep < 10) + emit tick(selectorStep * 10 + current * 10 / n, 100); current++; } } From a160f9aa991541a1739981a0565701887af737d4 Mon Sep 17 00:00:00 2001 From: szh <2659007320@qq.com> Date: Sat, 9 May 2026 11:42:11 +0800 Subject: [PATCH 3/7] fix multithreading support in gwr algorithms --- src/TaskThread/gwmbasicgwralgorithm.cpp | 15 ++++- src/TaskThread/gwmgeneralizedgwralgorithm.cpp | 28 ++++++--- .../gwmlocalcollinearitygwralgorithm.cpp | 57 ++++++++----------- .../gwmlocalcollinearitygwralgorithm.h | 18 +++--- src/TaskThread/gwmrobustgwralgorithm.cpp | 35 ++++-------- src/gwmlcrgwroptionsdialog.cpp | 4 +- 6 files changed, 80 insertions(+), 77 deletions(-) diff --git a/src/TaskThread/gwmbasicgwralgorithm.cpp b/src/TaskThread/gwmbasicgwralgorithm.cpp index e4cb4a3..c3ad9cb 100644 --- a/src/TaskThread/gwmbasicgwralgorithm.cpp +++ b/src/TaskThread/gwmbasicgwralgorithm.cpp @@ -1,4 +1,4 @@ -#include "gwmbasicgwralgorithm.h" +#include "gwmbasicgwralgorithm.h" #include #include #include @@ -138,11 +138,22 @@ void GwmBasicGWRAlgorithm::run() if (mIsAutoselectBandwidth) { emit message(QString(tr("Automatically selecting bandwidth ..."))); + qDebug() << "ParallelType in run before =" << mParallelType; + qDebug() << "OmpThreadNum in run before =" << mOmpThreadNum; mGWRCore->setParallelType(mParallelType); + mGWRCore->setOmpThreadNum(mOmpThreadNum); + qDebug() << "core parallelType =" << mGWRCore->parallelType(); + qDebug() << "core parallelAbility =" << mGWRCore->parallelAbility(); mGWRCore->setTelegram(std::make_unique(this)); + QElapsedTimer timer; + timer.start(); + mBetas = mGWRCore->fit(); + qint64 elapsed = timer.elapsed(); + qDebug() << "fit() time =" << elapsed << "ms"; + gwm::BandwidthWeight* bw = mGWRCore->spatialWeight().weight(); if (bw && !checkCanceled()) { @@ -155,7 +166,7 @@ void GwmBasicGWRAlgorithm::run() QVariant data = QVariant::fromValue(qlist); emit plot(data, &GwmBandwidthSizeSelector::PlotBandwidthResult); } - std::cout << "mBetas = \n" << mBetas << std::endl; + // std::cout << "mBetas = \n" << mBetas << std::endl; } else { diff --git a/src/TaskThread/gwmgeneralizedgwralgorithm.cpp b/src/TaskThread/gwmgeneralizedgwralgorithm.cpp index 00bdb5f..6dda9cf 100644 --- a/src/TaskThread/gwmgeneralizedgwralgorithm.cpp +++ b/src/TaskThread/gwmgeneralizedgwralgorithm.cpp @@ -853,6 +853,7 @@ double GwmGeneralizedGWRAlgorithm::bandwidthSizeGGWRCriterionCVOmp(GwmBandwidthW vec cv = vec(n); mat wt = mat(n,n); int current1 = 0, current2 = 0; + const int selectorStep = static_cast(mBandwidthSizeSelector.bandwidthCriterion().size()); #pragma omp parallel for num_threads(mOmpThreadNum) for (int i = 0; i < n; i++) { @@ -862,9 +863,11 @@ double GwmGeneralizedGWRAlgorithm::bandwidthSizeGGWRCriterionCVOmp(GwmBandwidthW vec w = bandwidthWeight->weight(d); w.row(i) = 0; wt.col(i) = w; - if(mBandwidthSizeSelector.counter<10) - emit tick(mBandwidthSizeSelector.counter*10 + current1 * 5 / n, 100); - current1++; + // if(mBandwidthSizeSelector.counter<10) + // emit tick(mBandwidthSizeSelector.counter*10 + current2 * 5 / n + 5, 100); + if (selectorStep < 10) + emit tick(selectorStep * 10 + current2 * 5 / n + 5, 100); + current2++; } } if (!checkCanceled()) (this->*mCalWtFunction)(mX,mY,wt); @@ -881,8 +884,10 @@ double GwmGeneralizedGWRAlgorithm::bandwidthSizeGGWRCriterionCVOmp(GwmBandwidthW else{ cv.row(i) = mY.row(i) - exp(yhatnoi)/(1+exp(yhatnoi)); } - if(mBandwidthSizeSelector.counter<10) - emit tick(mBandwidthSizeSelector.counter*10 + current2 * 5 / n + 5, 100); + // if(mBandwidthSizeSelector.counter<10) + // emit tick(mBandwidthSizeSelector.counter*10 + current2 * 5 / n + 5, 100); + if (selectorStep < 10) + emit tick(selectorStep * 10 + current2 * 5 / n + 5, 100); current2++; } } @@ -959,6 +964,7 @@ double GwmGeneralizedGWRAlgorithm::bandwidthSizeGGWRCriterionAICOmp(GwmBandwidth mat S = mat(n,n); mat wt = mat(n,n); int current1 = 0, current2 = 0; + const int selectorStep = static_cast(mBandwidthSizeSelector.bandwidthCriterion().size()); #pragma omp parallel for num_threads(mOmpThreadNum) for (int i = 0; i < n; i++) { @@ -967,8 +973,10 @@ double GwmGeneralizedGWRAlgorithm::bandwidthSizeGGWRCriterionAICOmp(GwmBandwidth vec d = mSpatialWeight.distance()->distance(i); vec w = bandwidthWeight->weight(d); wt.col(i) = w; - if(mBandwidthSizeSelector.counter<10) - emit tick(mBandwidthSizeSelector.counter*10 + current1 * 5 / n, 100); + // if(mBandwidthSizeSelector.counter<10) + // emit tick(mBandwidthSizeSelector.counter*10 + current1 * 5 / n, 100); + if (selectorStep < 10) + emit tick(selectorStep * 10 + current1 * 5 / n, 100); current1++; } } @@ -983,8 +991,10 @@ double GwmGeneralizedGWRAlgorithm::bandwidthSizeGGWRCriterionAICOmp(GwmBandwidth mat Ci = CiMat(mX,wi); S.row(i) = mX.row(i) * Ci; trS(thread) += S(i,i); - if(mBandwidthSizeSelector.counter<10) - emit tick(mBandwidthSizeSelector.counter*10 + current2 * 5 / n + 5, 100); + // if(mBandwidthSizeSelector.counter<10) + // emit tick(mBandwidthSizeSelector.counter*10 + current2 * 5 / n + 5, 100); + if (selectorStep < 10) + emit tick(selectorStep * 10 + current2 * 5 / n + 5, 100); current2++; } } diff --git a/src/TaskThread/gwmlocalcollinearitygwralgorithm.cpp b/src/TaskThread/gwmlocalcollinearitygwralgorithm.cpp index cc9365d..0eb7024 100644 --- a/src/TaskThread/gwmlocalcollinearitygwralgorithm.cpp +++ b/src/TaskThread/gwmlocalcollinearitygwralgorithm.cpp @@ -1,4 +1,4 @@ -#include "gwmlocalcollinearitygwralgorithm.h" +#include "gwmlocalcollinearitygwralgorithm.h" #include @@ -75,8 +75,20 @@ void GwmLocalCollinearityGWRAlgorithm::run() mLCGWRCore->setTelegram(std::make_unique(this)); + mLCGWRCore->setParallelType(mParallelType); + mLCGWRCore->setOmpThreadNum(mOmpThreadNum); + qDebug() << "core parallelType =" << mLCGWRCore->parallelType(); + qDebug() << "core parallelAbility =" << mLCGWRCore->parallelAbility(); + + QElapsedTimer timer; + timer.start(); + mBetas = mLCGWRCore->fit(); - std::cout << "mBetas = \n" << mBetas << std::endl; + + qint64 elapsed = timer.elapsed(); + qDebug() << "fit() time =" << elapsed << "ms"; + + // std::cout << "mBetas = \n" << mBetas << std::endl; gwm::BandwidthWeight* bw = mLCGWRCore->spatialWeight().weight(); mSpatialWeight.setWeight(bw); @@ -117,18 +129,18 @@ bool GwmLocalCollinearityGWRAlgorithm::isAutoselectBandwidth() const return mIsAutoselectBandwidth; } -void GwmLocalCollinearityGWRAlgorithm::setBandwidthSelectionCriterionType(const GwmLocalCollinearityGWRAlgorithm::BandwidthSelectionCriterionType &bandwidthSelectionCriterionType) +void GwmLocalCollinearityGWRAlgorithm::setBandwidthSelectionCriterionType(const gwm::GWRBasic::BandwidthSelectionCriterionType &bandwidthSelectionCriterionType) { mBandwidthSelectionCriterionType = bandwidthSelectionCriterionType; - QMap, BandwidthSelectCriterionFunction> mapper = { - std::make_pair(qMakePair(BandwidthSelectionCriterionType::CV, IParallelalbe::ParallelType::SerialOnly), &GwmLocalCollinearityGWRAlgorithm::bandwidthSizeCriterionCVSerial), + QMap, BandwidthSelectCriterionFunction> mapper = { + std::make_pair(qMakePair(gwm::GWRBasic::CV, gwm::ParallelType::SerialOnly), &GwmLocalCollinearityGWRAlgorithm::bandwidthSizeCriterionCVSerial), #ifdef ENABLE_OpenMP - std::make_pair(qMakePair(BandwidthSelectionCriterionType::CV, IParallelalbe::ParallelType::OpenMP), &GwmLocalCollinearityGWRAlgorithm::bandwidthSizeCriterionCVOmp), + std::make_pair(qMakePair(gwm::GWRBasic::CV, gwm::ParallelType::OpenMP), &GwmLocalCollinearityGWRAlgorithm::bandwidthSizeCriterionCVOmp), #endif - //std::make_pair(qMakePair(BandwidthSelectionCriterionType::CV, IParallelalbe::ParallelType::CUDA), &GwmLcrGWRTaskThread::bandwidthSizeCriterionCVCuda), - //std::make_pair(qMakePair(BandwidthSelectionCriterionType::AIC, IParallelalbe::ParallelType::SerialOnly), &GwmLcrGWRTaskThread::bandwidthSizeCriterionAICSerial), - //std::make_pair(qMakePair(BandwidthSelectionCriterionType::AIC, IParallelalbe::ParallelType::OpenMP), &GwmLcrGWRTaskThread::bandwidthSizeCriterionAICOmp), - //std::make_pair(qMakePair(BandwidthSelectionCriterionType::AIC, IParallelalbe::ParallelType::CUDA), &GwmLcrGWRTaskThread::bandwidthSizeCriterionAICCuda) + //std::make_pair(qMakePair(BandwidthSelectionCriterionType::CV, gwm::ParallelType::CUDA), &GwmLcrGWRTaskThread::bandwidthSizeCriterionCVCuda), + //std::make_pair(qMakePair(BandwidthSelectionCriterionType::AIC, gwm::ParallelType::SerialOnly), &GwmLcrGWRTaskThread::bandwidthSizeCriterionAICSerial), + //std::make_pair(qMakePair(BandwidthSelectionCriterionType::AIC, gwm::ParallelType::OpenMP), &GwmLcrGWRTaskThread::bandwidthSizeCriterionAICOmp), + //std::make_pair(qMakePair(BandwidthSelectionCriterionType::AIC, gwm::ParallelType::CUDA), &GwmLcrGWRTaskThread::bandwidthSizeCriterionAICCuda) }; mBandwidthSelectCriterionFunction = mapper[qMakePair(bandwidthSelectionCriterionType, mParallelType)]; } @@ -501,29 +513,10 @@ mat GwmLocalCollinearityGWRAlgorithm::regressionOmp(const mat &x, const vec &y) return betas; } #endif -void GwmLocalCollinearityGWRAlgorithm::setParallelType(const IParallelalbe::ParallelType &type) +void GwmLocalCollinearityGWRAlgorithm::setParallelType(const gwm::ParallelType &type) { - if(type & parallelAbility()) - { - mParallelType = type; - switch(type) - { - case IParallelalbe::ParallelType::SerialOnly: - setBandwidthSelectionCriterionType(mBandwidthSelectionCriterionType); - mRegressionFunction = &GwmLocalCollinearityGWRAlgorithm::regressionSerial; - break; -#ifdef ENABLE_OpenMP - case IParallelalbe::ParallelType::OpenMP: - setBandwidthSelectionCriterionType(mBandwidthSelectionCriterionType); - mRegressionFunction = &GwmLocalCollinearityGWRAlgorithm::regressionOmp; - break; -#endif - default: - setBandwidthSelectionCriterionType(mBandwidthSelectionCriterionType); - mRegressionFunction = &GwmLocalCollinearityGWRAlgorithm::regressionSerial; - break; - } - } + mParallelType = type; + mLCGWRCore->setParallelType(type); } bool GwmLocalCollinearityGWRAlgorithm::lambdaAdjust() const diff --git a/src/TaskThread/gwmlocalcollinearitygwralgorithm.h b/src/TaskThread/gwmlocalcollinearitygwralgorithm.h index 1e24c60..1e31761 100644 --- a/src/TaskThread/gwmlocalcollinearitygwralgorithm.h +++ b/src/TaskThread/gwmlocalcollinearitygwralgorithm.h @@ -11,7 +11,7 @@ using namespace arma; -class GwmLocalCollinearityGWRAlgorithm:public GwmGeographicalWeightedRegressionAlgorithm, public IBandwidthSizeSelectable,public IOpenmpParallelable +class GwmLocalCollinearityGWRAlgorithm:public GwmGeographicalWeightedRegressionAlgorithm, public IBandwidthSizeSelectable, public IIndependentVariableSelectable, public gwm::IParallelizable, public gwm::IParallelOpenmpEnabled, public gwm::IParallelCudaEnabled { public: @@ -71,8 +71,8 @@ class GwmLocalCollinearityGWRAlgorithm:public GwmGeographicalWeightedRegressionA return criterionList; } - BandwidthSelectionCriterionType bandwidthSelectionCriterionType() const; - void setBandwidthSelectionCriterionType(const BandwidthSelectionCriterionType &bandwidthSelectionCriterionType); + gwm::GWRBasic::BandwidthSelectionCriterionType bandwidthSelectionCriterionType() const; + void setBandwidthSelectionCriterionType(const gwm::GWRBasic::BandwidthSelectionCriterionType &bandwidthSelectionCriterionType); public: bool isValid() override; @@ -92,9 +92,9 @@ class GwmLocalCollinearityGWRAlgorithm:public GwmGeographicalWeightedRegressionA void createResultLayer(CreateResultLayerData data); public: int parallelAbility() const override; - ParallelType parallelType() const override; + gwm::ParallelType parallelType() const override; - void setParallelType(const ParallelType &type) override; + void setParallelType(const gwm::ParallelType &type) override; // IOpenmpParallelable interface public: @@ -127,7 +127,7 @@ class GwmLocalCollinearityGWRAlgorithm:public GwmGeographicalWeightedRegressionA #ifdef ENABLE_OpenMP double bandwidthSizeCriterionCVOmp(GwmBandwidthWeight* weight); #endif - BandwidthSelectionCriterionType mBandwidthSelectionCriterionType = BandwidthSelectionCriterionType::CV; + gwm::GWRBasic::BandwidthSelectionCriterionType mBandwidthSelectionCriterionType = gwm::GWRBasic::BandwidthSelectionCriterionType::CV; BandwidthSelectCriterionFunction mBandwidthSelectCriterionFunction = &GwmLocalCollinearityGWRAlgorithm::bandwidthSizeCriterionCVSerial; mat regressionSerial(const mat& x, const vec& y); @@ -136,7 +136,7 @@ class GwmLocalCollinearityGWRAlgorithm:public GwmGeographicalWeightedRegressionA #endif Regression mRegressionFunction = &GwmLocalCollinearityGWRAlgorithm::regressionSerial; - IParallelalbe::ParallelType mParallelType = IParallelalbe::ParallelType::SerialOnly; + gwm::ParallelType mParallelType = gwm::ParallelType::SerialOnly; int mOmpThreadNum = 8; int mGpuId = 0; int mGroupSize = 64; @@ -146,10 +146,10 @@ class GwmLocalCollinearityGWRAlgorithm:public GwmGeographicalWeightedRegressionA inline int GwmLocalCollinearityGWRAlgorithm::parallelAbility() const { - return IParallelalbe::SerialOnly | IParallelalbe::OpenMP; + return gwm::SerialOnly | gwm::OpenMP; } -inline IParallelalbe::ParallelType GwmLocalCollinearityGWRAlgorithm::parallelType() const +inline gwm::ParallelType GwmLocalCollinearityGWRAlgorithm::parallelType() const { return mParallelType; } diff --git a/src/TaskThread/gwmrobustgwralgorithm.cpp b/src/TaskThread/gwmrobustgwralgorithm.cpp index fe9e9e1..a595735 100644 --- a/src/TaskThread/gwmrobustgwralgorithm.cpp +++ b/src/TaskThread/gwmrobustgwralgorithm.cpp @@ -55,9 +55,20 @@ void GwmRobustGWRAlgorithm::run() { emit message("Regression ..."); mRGWRCore->setParallelType(mParallelType); + mRGWRCore->setOmpThreadNum(mOmpThreadNum); + qDebug() << "core parallelType =" << mRGWRCore->parallelType(); + qDebug() << "core parallelAbility =" << mRGWRCore->parallelAbility(); mRGWRCore->setTelegram(std::make_unique(this)); + + QElapsedTimer timer; + timer.start(); + mBetas = mRGWRCore->fit(); - qDebug() << "mBetas:"; mBetas.print(); + + qint64 elapsed = timer.elapsed(); + qDebug() << "fit() time =" << elapsed << "ms"; + + // qDebug() << "mBetas:"; mBetas.print(); } if(mOLS&&!checkCanceled()){ @@ -259,28 +270,6 @@ void GwmRobustGWRAlgorithm::createResultLayer(CreateResultLayerData data) void GwmRobustGWRAlgorithm::setParallelType(const gwm::ParallelType &type) { GwmBasicGWRAlgorithm::setParallelType(type); - if (type & parallelAbility()) - { - mParallelType = type; - switch (type) { - case gwm::ParallelType::SerialOnly: - mRegressionHatmatrixFunction = &GwmRobustGWRAlgorithm::regressionHatmatrixSerial; - break; -#ifdef ENABLE_OpenMP - case gwm::ParallelType::OpenMP: - mRegressionHatmatrixFunction = &GwmRobustGWRAlgorithm::regressionHatmatrixOmp; - break; -#endif -#ifdef ENABLE_CUDA - case gwm::ParallelType::CUDA: - mRegressionHatmatrixFunction = &GwmRobustGWRAlgorithm::regressionHatmatrixCuda; - break; -#endif - default: - mRegressionHatmatrixFunction = &GwmRobustGWRAlgorithm::regressionHatmatrixSerial; - break; - } - } } mat GwmRobustGWRAlgorithm::robustGWRCaliFirst(const mat &x, const vec &y, mat &betasSE, vec &shat, vec &qDiag, mat &S) diff --git a/src/gwmlcrgwroptionsdialog.cpp b/src/gwmlcrgwroptionsdialog.cpp index e4e91b1..0610fac 100644 --- a/src/gwmlcrgwroptionsdialog.cpp +++ b/src/gwmlcrgwroptionsdialog.cpp @@ -498,11 +498,11 @@ void GwmLcrGWROptionsDialog::updateFields() // 并行设置 if (ui->mCalcParallelNoneRadio->isChecked()) { - mTaskThread->setParallelType(IParallelalbe::SerialOnly); + mTaskThread->setParallelType(gwm::SerialOnly); } else if (ui->mCalcParallelMultithreadRadio->isChecked()) { - mTaskThread->setParallelType(IParallelalbe::OpenMP); + mTaskThread->setParallelType(gwm::OpenMP); mTaskThread->setOmpThreadNum(ui->mThreadNum->value()); } // 其他设置 From 8de413fdff8732da1158f1b3583cc4c1b83e2d44 Mon Sep 17 00:00:00 2001 From: szh <2659007320@qq.com> Date: Thu, 14 May 2026 16:04:59 +0800 Subject: [PATCH 4/7] 111 --- src/TaskThread/gwmbasicgwralgorithm.cpp | 4 ++-- src/TaskThread/gwmgwaveragetaskthread.cpp | 4 +++- src/TaskThread/gwmgwcorrelationtaskthread.cpp | 2 ++ src/TaskThread/gwmgwpcataskthread.cpp | 2 +- src/TaskThread/gwmlocalcollinearitygwralgorithm.cpp | 4 ++-- src/TaskThread/gwmrobustgwralgorithm.cpp | 2 +- src/gwmgwcorrelationoptionsdialog.cpp | 2 +- 7 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/TaskThread/gwmbasicgwralgorithm.cpp b/src/TaskThread/gwmbasicgwralgorithm.cpp index c3ad9cb..559ac2d 100644 --- a/src/TaskThread/gwmbasicgwralgorithm.cpp +++ b/src/TaskThread/gwmbasicgwralgorithm.cpp @@ -1547,6 +1547,6 @@ void GwmBasicGWRAlgorithm::setBandwidthSelectionCriterionType(const gwm::GWRBasi void GwmBasicGWRAlgorithm::setParallelType(const gwm::ParallelType &type) { - mParallelType = type; - mGWRCore->setParallelType(type); + // mParallelType = type; + // mGWRCore->setParallelType(type); } diff --git a/src/TaskThread/gwmgwaveragetaskthread.cpp b/src/TaskThread/gwmgwaveragetaskthread.cpp index 480c760..2bf54d8 100644 --- a/src/TaskThread/gwmgwaveragetaskthread.cpp +++ b/src/TaskThread/gwmgwaveragetaskthread.cpp @@ -1,4 +1,4 @@ -#include "gwmgwaveragetaskthread.h" +#include "gwmgwaveragetaskthread.h" #include #include #include "SpatialWeight/gwmcrsdistance.h" @@ -75,6 +75,8 @@ void GwmGWAverageTaskThread::run() try { mAlgorithm.setTelegram(make_unique(this)); + qDebug() << "core parallelType =" << mAlgorithm.parallelType(); + qDebug() << "core parallelAbility =" << mAlgorithm.parallelAbility(); mAlgorithm.run(); if(!checkCanceled()) { diff --git a/src/TaskThread/gwmgwcorrelationtaskthread.cpp b/src/TaskThread/gwmgwcorrelationtaskthread.cpp index 80216fc..03b3c56 100644 --- a/src/TaskThread/gwmgwcorrelationtaskthread.cpp +++ b/src/TaskThread/gwmgwcorrelationtaskthread.cpp @@ -197,6 +197,8 @@ void GwmGWCorrelationTaskThread::run() mGWCorrCore->setBandwidthSelectionApproach(bandwidthSelTypes); mGWCorrCore->setParallelType(static_cast(mParallelType)); mGWCorrCore->setOmpThreadNum(mOmpThreadNum); + qDebug() << "core parallelType =" << mGWCorrCore->parallelType(); + qDebug() << "core parallelAbility =" << mGWCorrCore->parallelAbility(); // std::vector a = mGWCorrCore->spatialWeights(); // gwm::BandwidthWeight bwa = a[0].weight(); diff --git a/src/TaskThread/gwmgwpcataskthread.cpp b/src/TaskThread/gwmgwpcataskthread.cpp index 43045a6..385a2e2 100644 --- a/src/TaskThread/gwmgwpcataskthread.cpp +++ b/src/TaskThread/gwmgwpcataskthread.cpp @@ -1,4 +1,4 @@ -#include "gwmgwpcataskthread.h" +#include "gwmgwpcataskthread.h" #include #include "TaskThread/gwmgeographicalweightedregressionalgorithm.h" #include "gwmtaskthread.h" diff --git a/src/TaskThread/gwmlocalcollinearitygwralgorithm.cpp b/src/TaskThread/gwmlocalcollinearitygwralgorithm.cpp index 0eb7024..d4f05cf 100644 --- a/src/TaskThread/gwmlocalcollinearitygwralgorithm.cpp +++ b/src/TaskThread/gwmlocalcollinearitygwralgorithm.cpp @@ -515,8 +515,8 @@ mat GwmLocalCollinearityGWRAlgorithm::regressionOmp(const mat &x, const vec &y) #endif void GwmLocalCollinearityGWRAlgorithm::setParallelType(const gwm::ParallelType &type) { - mParallelType = type; - mLCGWRCore->setParallelType(type); + // mParallelType = type; + // mLCGWRCore->setParallelType(type); } bool GwmLocalCollinearityGWRAlgorithm::lambdaAdjust() const diff --git a/src/TaskThread/gwmrobustgwralgorithm.cpp b/src/TaskThread/gwmrobustgwralgorithm.cpp index a595735..7ec099c 100644 --- a/src/TaskThread/gwmrobustgwralgorithm.cpp +++ b/src/TaskThread/gwmrobustgwralgorithm.cpp @@ -269,7 +269,7 @@ void GwmRobustGWRAlgorithm::createResultLayer(CreateResultLayerData data) void GwmRobustGWRAlgorithm::setParallelType(const gwm::ParallelType &type) { - GwmBasicGWRAlgorithm::setParallelType(type); + // GwmBasicGWRAlgorithm::setParallelType(type); } mat GwmRobustGWRAlgorithm::robustGWRCaliFirst(const mat &x, const vec &y, mat &betasSE, vec &shat, vec &qDiag, mat &S) diff --git a/src/gwmgwcorrelationoptionsdialog.cpp b/src/gwmgwcorrelationoptionsdialog.cpp index a6f6872..deca301 100644 --- a/src/gwmgwcorrelationoptionsdialog.cpp +++ b/src/gwmgwcorrelationoptionsdialog.cpp @@ -1,4 +1,4 @@ -#include "gwmgwcorrelationoptionsdialog.h" +#include "gwmgwcorrelationoptionsdialog.h" #include "ui_gwmgwcorrelationoptionsdialog.h" #ifdef ENABLE_OpenMP #include From b211d978fa560c6d3ebb83a8dfd369cc63bc6adc Mon Sep 17 00:00:00 2001 From: szh <2659007320@qq.com> Date: Mon, 18 May 2026 15:52:57 +0800 Subject: [PATCH 5/7] 123 --- src/Model/gwmalgorithmmetavariable.cpp | 2 +- src/Model/gwmalgorithmmetavariable.h | 1 + src/TaskThread/gwmgwaveragetaskthread.cpp | 3 + src/gwmgwaverageoptionsdialog.cpp | 40 ++++++++++++- src/gwmgwaverageoptionsdialog.h | 3 + src/gwmgwaverageoptionsdialog.ui | 68 +++++++++++++++++++---- 6 files changed, 103 insertions(+), 14 deletions(-) diff --git a/src/Model/gwmalgorithmmetavariable.cpp b/src/Model/gwmalgorithmmetavariable.cpp index 0aa5bbb..05b20b1 100644 --- a/src/Model/gwmalgorithmmetavariable.cpp +++ b/src/Model/gwmalgorithmmetavariable.cpp @@ -20,7 +20,7 @@ bool GwmAlgorithmMetaVariable::validate(QString &error) const if (weightType == Weight::WeightType::BandwidthWeight) { - if (weightBandwidthSize == 0) + if (!weightBandwidthAutoselect && weightBandwidthSize == 0) { error = QTranslator::tr("Bandwidth size is too small."); return false; diff --git a/src/Model/gwmalgorithmmetavariable.h b/src/Model/gwmalgorithmmetavariable.h index 4b13418..3cf400d 100644 --- a/src/Model/gwmalgorithmmetavariable.h +++ b/src/Model/gwmalgorithmmetavariable.h @@ -14,6 +14,7 @@ struct GwmAlgorithmMetaVariable gwm::Weight::WeightType weightType = gwm::Weight::BandwidthWeight; double weightBandwidthSize = DBL_MAX; bool weightBandwidthAdaptive = true; + bool weightBandwidthAutoselect = false; gwm::BandwidthWeight::KernelFunctionType weightBandwidthKernel = gwm::BandwidthWeight::KernelFunctionType::Gaussian; // Distance gwm::Distance::DistanceType distanceType = gwm::Distance::DistanceType::CRSDistance; diff --git a/src/TaskThread/gwmgwaveragetaskthread.cpp b/src/TaskThread/gwmgwaveragetaskthread.cpp index 2bf54d8..f3b41cb 100644 --- a/src/TaskThread/gwmgwaveragetaskthread.cpp +++ b/src/TaskThread/gwmgwaveragetaskthread.cpp @@ -45,6 +45,7 @@ GwmGWAverageTaskThread::GwmGWAverageTaskThread(const GwmAlgorithmMetaVariable& m } SpatialWeight spatialWeight(&weight, distance); mAlgorithm.setSpatialWeight(spatialWeight); + mAlgorithm.setAutoselectBandwidth(meta.weightBandwidthAutoselect); // Parallel mAlgorithm.setParallelType(meta.parallelType); switch (meta.parallelType) @@ -77,7 +78,9 @@ void GwmGWAverageTaskThread::run() mAlgorithm.setTelegram(make_unique(this)); qDebug() << "core parallelType =" << mAlgorithm.parallelType(); qDebug() << "core parallelAbility =" << mAlgorithm.parallelAbility(); + qDebug() << "core autoselect bandwidth =" << mAlgorithm.isAutoselectBandwidth(); mAlgorithm.run(); + qDebug() << "runfinished"; if(!checkCanceled()) { mResultList.push_back(qMakePair(QString("LM"), localmean())); diff --git a/src/gwmgwaverageoptionsdialog.cpp b/src/gwmgwaverageoptionsdialog.cpp index 974e194..ac47a1f 100644 --- a/src/gwmgwaverageoptionsdialog.cpp +++ b/src/gwmgwaverageoptionsdialog.cpp @@ -37,6 +37,11 @@ GwmGWAverageOptionsDialog::GwmGWAverageOptionsDialog(QList o connect(ui->mBwTypeFixedRadio, &QAbstractButton::toggled, this, &GwmGWAverageOptionsDialog::onFixedRadioToggled); connect(ui->mBwTypeAdaptiveRadio, &QAbstractButton::toggled, this, &GwmGWAverageOptionsDialog::onVariableRadioToggled); + QButtonGroup* bwSelectionBtnGroup = new QButtonGroup(this); + bwSelectionBtnGroup->addButton(ui->mBwSizeAutomaticRadio); + bwSelectionBtnGroup->addButton(ui->mBwSizeCustomizeRadio); + connect(ui->mBwSizeAutomaticRadio, &QAbstractButton::toggled, this, &GwmGWAverageOptionsDialog::onAutomaticRadioToggled); + connect(ui->mBwSizeCustomizeRadio, &QAbstractButton::toggled, this, &GwmGWAverageOptionsDialog::onCustomizeRadioToggled); //距离计算部分 QButtonGroup* distanceSettingBtnGroup = new QButtonGroup(this); @@ -70,6 +75,8 @@ GwmGWAverageOptionsDialog::GwmGWAverageOptionsDialog(QList o connect(ui->mIndepVarSelector, &GwmIndepVarSelectorWidget::selectedIndepVarChangedSignal, this, &GwmGWAverageOptionsDialog::updateFieldsAndEnable); connect(ui->mBwTypeFixedRadio, &QAbstractButton::toggled, this, &GwmGWAverageOptionsDialog::updateFieldsAndEnable); connect(ui->mBwTypeAdaptiveRadio, &QAbstractButton::toggled, this, &GwmGWAverageOptionsDialog::updateFieldsAndEnable); + connect(ui->mBwSizeAutomaticRadio, &QAbstractButton::toggled, this, &GwmGWAverageOptionsDialog::updateFieldsAndEnable); + connect(ui->mBwSizeCustomizeRadio, &QAbstractButton::toggled, this, &GwmGWAverageOptionsDialog::updateFieldsAndEnable); connect(ui->mBwSizeFixedSize, static_cast(&QDoubleSpinBox::valueChanged), this, &GwmGWAverageOptionsDialog::updateFieldsAndEnable); connect(ui->mBwSizeFixedUnit, static_cast(&QComboBox::currentIndexChanged), this, &GwmGWAverageOptionsDialog::updateFieldsAndEnable); connect(ui->mBwSizeAdaptiveSize, static_cast(&QSpinBox::valueChanged), this, &GwmGWAverageOptionsDialog::updateFieldsAndEnable); @@ -91,6 +98,9 @@ GwmGWAverageOptionsDialog::GwmGWAverageOptionsDialog(QList o ui->mBwSizeAdaptiveSize->setMaximum(INT_MAX); ui->mBwSizeFixedSize->setMaximum(DBL_MAX); + ui->mBwTypeAdaptiveRadio->setChecked(true); + ui->mBwSizeAutomaticRadio->setChecked(true); + onAutomaticRadioToggled(ui->mBwSizeAutomaticRadio->isChecked()); ui->mDistTypeCRSRadio->setChecked(true); updateFieldsAndEnable(); } @@ -257,6 +267,33 @@ void GwmGWAverageOptionsDialog::onVariableRadioToggled(bool checked) ui->mBwSizeSettingStack->setCurrentIndex(0); } +void GwmGWAverageOptionsDialog::onAutomaticRadioToggled(bool checked) +{ + if (checked) + { + ui->mBwSizeAdaptiveSize->setEnabled(false); + ui->mBwSizeAdaptiveUnit->setEnabled(false); + ui->mBwSizeFixedSize->setEnabled(false); + ui->mBwSizeFixedUnit->setEnabled(false); + } +} + +void GwmGWAverageOptionsDialog::onCustomizeRadioToggled(bool checked) +{ + if (checked) + { + ui->mBwSizeAdaptiveSize->setEnabled(true); + ui->mBwSizeAdaptiveUnit->setEnabled(true); + ui->mBwSizeFixedSize->setEnabled(true); + ui->mBwSizeFixedUnit->setEnabled(true); + } +} + +bool GwmGWAverageOptionsDialog::bandwidthAutoSelect() +{ + return ui->mBwSizeAutomaticRadio->isChecked(); +} + double GwmGWAverageOptionsDialog::bandwidthSize(){ if (ui->mBwTypeAdaptiveRadio->isChecked()) { @@ -324,8 +361,9 @@ void GwmGWAverageOptionsDialog::updateFields() } mAlgorithmMeta.weightType = gwm::Weight::BandwidthWeight; - mAlgorithmMeta.weightBandwidthSize = bandwidthSize(); + mAlgorithmMeta.weightBandwidthSize = bandwidthAutoSelect() ? 1.0 : bandwidthSize(); mAlgorithmMeta.weightBandwidthAdaptive = bandwidthType(); + mAlgorithmMeta.weightBandwidthAutoselect = bandwidthAutoSelect(); mAlgorithmMeta.weightBandwidthKernel = bandwidthKernelFunction(); diff --git a/src/gwmgwaverageoptionsdialog.h b/src/gwmgwaverageoptionsdialog.h index fb9ceff..153d09f 100644 --- a/src/gwmgwaverageoptionsdialog.h +++ b/src/gwmgwaverageoptionsdialog.h @@ -38,6 +38,8 @@ public slots: void onFixedRadioToggled(bool checked); void onVariableRadioToggled(bool checked); + void onAutomaticRadioToggled(bool checked); + void onCustomizeRadioToggled(bool checked); void onNoneRadioToggled(bool checked); void onMultithreadingRadioToggled(bool checked); void onGPURadioToggled(bool checked); @@ -52,6 +54,7 @@ public slots: QString crsRotateTheta(); QString crsRotateP(); bool bandwidthType(); + bool bandwidthAutoSelect(); IParallelalbe::ParallelType approachType(); double bandwidthSize(); gwm::BandwidthWeight::KernelFunctionType bandwidthKernelFunction(); diff --git a/src/gwmgwaverageoptionsdialog.ui b/src/gwmgwaverageoptionsdialog.ui index 41a9d56..7032322 100644 --- a/src/gwmgwaverageoptionsdialog.ui +++ b/src/gwmgwaverageoptionsdialog.ui @@ -27,8 +27,8 @@ 0 0 - 600 - 650 + 644 + 778 @@ -144,7 +144,58 @@ + + + + Bandwidth Selection + + + + + + 6 + + + + + Automatic + + + true + + + + + + + Customize + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Bandwidth Size + + + + 0 @@ -252,14 +303,14 @@ - + Kernel Function - + @@ -288,13 +339,6 @@ - - - - Bandwidth Size - - - @@ -705,4 +749,4 @@ - \ No newline at end of file + From 7091f5b7b5d90e87d8cf20926e0023a71b274e5c Mon Sep 17 00:00:00 2001 From: szh <2659007320@qq.com> Date: Thu, 21 May 2026 14:43:23 +0800 Subject: [PATCH 6/7] anova --- src/Model/gwmlayergwaverageitem.cpp | 11 ++++++- .../gwmpropertygwaveragetab.cpp | 6 ++++ src/TaskThread/gwmgwaveragetaskthread.cpp | 32 +++++++++++++++++++ src/TaskThread/gwmgwaveragetaskthread.h | 5 ++- .../gwmlocalcollinearitygwralgorithm.cpp | 17 ++++++++-- .../gwmlocalcollinearitygwralgorithm.h | 12 +++++-- 6 files changed, 77 insertions(+), 6 deletions(-) diff --git a/src/Model/gwmlayergwaverageitem.cpp b/src/Model/gwmlayergwaverageitem.cpp index 1a6461e..72b7ed6 100644 --- a/src/Model/gwmlayergwaverageitem.cpp +++ b/src/Model/gwmlayergwaverageitem.cpp @@ -9,7 +9,16 @@ GwmLayerGWAverageItem::GwmLayerGWAverageItem(GwmLayerItem* parentItem, QgsVector auto taskMeta = taskThread->meta(); mDataPointsSize = taskMeta.layer->featureCount(); mVariables = taskMeta.variables; - mBandwidth = new gwm::BandwidthWeight(taskMeta.weightBandwidthSize, taskMeta.weightBandwidthAdaptive, gwm::BandwidthWeight::KernelFunctionType(taskMeta.weightBandwidthKernel)); + // Use final bandwidth from taskThread (may be updated by autoselect), fallback to meta + gwm::BandwidthWeight finalBw = taskThread->finalBandwidth(); + if (finalBw.bandwidth() != 0.0 || finalBw.adaptive()) + { + mBandwidth = new gwm::BandwidthWeight(finalBw); + } + else + { + mBandwidth = new gwm::BandwidthWeight(taskMeta.weightBandwidthSize, taskMeta.weightBandwidthAdaptive, gwm::BandwidthWeight::KernelFunctionType(taskMeta.weightBandwidthKernel)); + } mQuantile = taskThread->quantile(); mResultList = taskThread->resultlist(); diff --git a/src/PropertyPanelTabs/gwmpropertygwaveragetab.cpp b/src/PropertyPanelTabs/gwmpropertygwaveragetab.cpp index 28d624a..00e1304 100644 --- a/src/PropertyPanelTabs/gwmpropertygwaveragetab.cpp +++ b/src/PropertyPanelTabs/gwmpropertygwaveragetab.cpp @@ -53,6 +53,12 @@ void GwmPropertyGWAverageTab::updateUI() QString bwSizeString = QString("%1 (number of nearest neighbours)").arg(int(weight.bandwidth())); ui->lblBandwidthSize->setText(bwSizeString); } + else + { + // for fixed bandwidth show distance value + QString bwSizeString = QString("%1 (distance)").arg(weight.bandwidth(), 0, 'f', 3); + ui->lblBandwidthSize->setText(bwSizeString); + } ui->lblNumberDataPoints->setText(QString("%1").arg(mLayerItem->dataPointsSize())); if (true) { diff --git a/src/TaskThread/gwmgwaveragetaskthread.cpp b/src/TaskThread/gwmgwaveragetaskthread.cpp index f3b41cb..15a7ad1 100644 --- a/src/TaskThread/gwmgwaveragetaskthread.cpp +++ b/src/TaskThread/gwmgwaveragetaskthread.cpp @@ -46,6 +46,10 @@ GwmGWAverageTaskThread::GwmGWAverageTaskThread(const GwmAlgorithmMetaVariable& m SpatialWeight spatialWeight(&weight, distance); mAlgorithm.setSpatialWeight(spatialWeight); mAlgorithm.setAutoselectBandwidth(meta.weightBandwidthAutoselect); + qDebug() << "GWAverageTaskThread configured: autoselectBandwidth=" << mAlgorithm.isAutoselectBandwidth() + << ", initial bandwidth=" << weight.bandwidth() + << ", adaptive=" << weight.adaptive() + << ", kernel=" << (int)weight.kernel(); // Parallel mAlgorithm.setParallelType(meta.parallelType); switch (meta.parallelType) @@ -61,6 +65,14 @@ GwmGWAverageTaskThread::GwmGWAverageTaskThread(const GwmAlgorithmMetaVariable& m delete distance; } +gwm::BandwidthWeight GwmGWAverageTaskThread::finalBandwidth() const +{ + auto bw = mAlgorithm.spatialWeight().weight(); + if (bw) + return *bw; + return gwm::BandwidthWeight(); +} + void GwmGWAverageTaskThread::run() { emit tick(0, 0); @@ -79,8 +91,28 @@ void GwmGWAverageTaskThread::run() qDebug() << "core parallelType =" << mAlgorithm.parallelType(); qDebug() << "core parallelAbility =" << mAlgorithm.parallelAbility(); qDebug() << "core autoselect bandwidth =" << mAlgorithm.isAutoselectBandwidth(); + if (mAlgorithm.isAutoselectBandwidth()) + { + auto bw = mAlgorithm.spatialWeight().weight(); + if (bw) + { + qDebug() << "core bandwidth before run =" << bw->bandwidth() + << ", adaptive =" << bw->adaptive() + << ", kernel =" << (int)bw->kernel(); + } + } mAlgorithm.run(); qDebug() << "runfinished"; + if (mAlgorithm.isAutoselectBandwidth()) + { + auto bw = mAlgorithm.spatialWeight().weight(); + if (bw) + { + qDebug() << "core bandwidth after run =" << bw->bandwidth() + << ", adaptive =" << bw->adaptive() + << ", kernel =" << (int)bw->kernel(); + } + } if(!checkCanceled()) { mResultList.push_back(qMakePair(QString("LM"), localmean())); diff --git a/src/TaskThread/gwmgwaveragetaskthread.h b/src/TaskThread/gwmgwaveragetaskthread.h index bde7314..9c51652 100644 --- a/src/TaskThread/gwmgwaveragetaskthread.h +++ b/src/TaskThread/gwmgwaveragetaskthread.h @@ -1,4 +1,4 @@ -#ifndef GWMGWAVERAGETASKTHREAD_H +#ifndef GWMGWAVERAGETASKTHREAD_H #define GWMGWAVERAGETASKTHREAD_H #include @@ -74,6 +74,9 @@ class GwmGWAverageTaskThread : public GwmSpatialMonoscaleAlgorithm, public IGwmM QList mVariables; CreateResultLayerData mResultList; +public: + gwm::BandwidthWeight finalBandwidth() const; + public: static int treeChildCount; diff --git a/src/TaskThread/gwmlocalcollinearitygwralgorithm.cpp b/src/TaskThread/gwmlocalcollinearitygwralgorithm.cpp index d4f05cf..7d83f18 100644 --- a/src/TaskThread/gwmlocalcollinearitygwralgorithm.cpp +++ b/src/TaskThread/gwmlocalcollinearitygwralgorithm.cpp @@ -43,6 +43,16 @@ void GwmLocalCollinearityGWRAlgorithm::setCanceled(bool canceled) return GwmTaskThread::setCanceled(canceled); } +void GwmLocalCollinearityGWRAlgorithm::setGPUId(const int gpuId) +{ + mGpuId = gpuId; +} + +void GwmLocalCollinearityGWRAlgorithm::setGroupSize(const std::size_t size) +{ + mGroupSize = static_cast(size); +} + void GwmLocalCollinearityGWRAlgorithm::run() { if(!checkCanceled()) @@ -515,8 +525,11 @@ mat GwmLocalCollinearityGWRAlgorithm::regressionOmp(const mat &x, const vec &y) #endif void GwmLocalCollinearityGWRAlgorithm::setParallelType(const gwm::ParallelType &type) { - // mParallelType = type; - // mLCGWRCore->setParallelType(type); + if (mLCGWRCore && (type & mLCGWRCore->parallelAbility())) + { + mParallelType = type; + mLCGWRCore->setParallelType(type); + } } bool GwmLocalCollinearityGWRAlgorithm::lambdaAdjust() const diff --git a/src/TaskThread/gwmlocalcollinearitygwralgorithm.h b/src/TaskThread/gwmlocalcollinearitygwralgorithm.h index 1e31761..cc25739 100644 --- a/src/TaskThread/gwmlocalcollinearitygwralgorithm.h +++ b/src/TaskThread/gwmlocalcollinearitygwralgorithm.h @@ -11,7 +11,7 @@ using namespace arma; -class GwmLocalCollinearityGWRAlgorithm:public GwmGeographicalWeightedRegressionAlgorithm, public IBandwidthSizeSelectable, public IIndependentVariableSelectable, public gwm::IParallelizable, public gwm::IParallelOpenmpEnabled, public gwm::IParallelCudaEnabled +class GwmLocalCollinearityGWRAlgorithm:public GwmGeographicalWeightedRegressionAlgorithm, public IBandwidthSizeSelectable, public gwm::IParallelizable, public gwm::IParallelOpenmpEnabled, public gwm::IParallelCudaEnabled { public: @@ -100,6 +100,10 @@ class GwmLocalCollinearityGWRAlgorithm:public GwmGeographicalWeightedRegressionA public: void setOmpThreadNum(const int threadNum) override; + // IParallelCudaEnabled interface + void setGPUId(const int gpuId) override; + void setGroupSize(const std::size_t size) override; + void setCanceled(bool canceled) override; private: double mLambda; @@ -146,7 +150,7 @@ class GwmLocalCollinearityGWRAlgorithm:public GwmGeographicalWeightedRegressionA inline int GwmLocalCollinearityGWRAlgorithm::parallelAbility() const { - return gwm::SerialOnly | gwm::OpenMP; + return mLCGWRCore ? mLCGWRCore->parallelAbility() : (gwm::SerialOnly | gwm::OpenMP); } inline gwm::ParallelType GwmLocalCollinearityGWRAlgorithm::parallelType() const @@ -157,6 +161,10 @@ inline gwm::ParallelType GwmLocalCollinearityGWRAlgorithm::parallelType() const inline void GwmLocalCollinearityGWRAlgorithm::setOmpThreadNum(const int threadNum) { mOmpThreadNum = threadNum; + if (mLCGWRCore) + { + mLCGWRCore->setOmpThreadNum(threadNum); + } } #endif // GWMLCRGWRTASKTHREAD_H From 272a97b8629faf5daf9fa48bda223bb2664474f1 Mon Sep 17 00:00:00 2001 From: szh <2659007320@qq.com> Date: Fri, 10 Jul 2026 11:03:59 +0800 Subject: [PATCH 7/7] Restore unrelated files to master --- src/CMakeLists.txt | 6 +- src/Model/gwmlayerbasicgwritem.cpp | 2 +- src/Model/gwmlayercollinearitygwritem.cpp | 2 +- src/Model/gwmlayerggwritem.cpp | 2 +- src/Model/gwmlayergtdritem.cpp | 22 +- src/Model/gwmlayergwpcaitem.cpp | 11 +- src/Model/gwmlayerscalablegwritem.cpp | 2 +- src/TaskThread/gwmbasicgwralgorithm.cpp | 227 +++++++++--------- src/TaskThread/gwmbasicgwralgorithm.h | 4 +- src/TaskThread/gwmgeneralizedgwralgorithm.cpp | 135 ++++++----- src/TaskThread/gwmgeneralizedgwralgorithm.h | 7 +- ...eographicalweightedregressionalgorithm.cpp | 20 +- src/TaskThread/gwmgtdrtaskthread.cpp | 81 ++++--- src/TaskThread/gwmgtdrtaskthread.h | 2 +- src/TaskThread/gwmgtwralgorithm.cpp | 66 +++-- src/TaskThread/gwmgtwralgorithm.h | 51 ++-- src/TaskThread/gwmgwcorrelationtaskthread.cpp | 59 ++--- src/TaskThread/gwmgwpcataskthread.cpp | 198 ++++++++------- src/TaskThread/gwmgwpcataskthread.h | 11 +- .../gwmlocalcollinearitygwralgorithm.cpp | 91 +++---- .../gwmlocalcollinearitygwralgorithm.h | 28 +-- src/TaskThread/gwmmultiscalegwralgorithm.cpp | 112 +++------ src/TaskThread/gwmmultiscalegwralgorithm.h | 28 ++- src/TaskThread/gwmrobustgwralgorithm.cpp | 61 +++-- src/TaskThread/gwmscalablegwralgorithm.cpp | 56 ++--- src/TaskThread/gwmswimtaskthread.cpp | 2 +- src/gwmggwroptionsdialog.cpp | 11 +- src/gwmggwroptionsdialog.ui | 3 + src/gwmgtdroptionsdialog.cpp | 4 +- src/gwmgtdroptionsdialog.ui | 3 + src/gwmgtwroptionsdialog.cpp | 10 +- src/gwmgwcorrelationoptionsdialog.cpp | 4 +- src/gwmgwpcaoptionsdialog.cpp | 4 +- src/gwmgwpcaoptionsdialog.ui | 3 + src/gwmgwroptionsdialog.cpp | 4 +- src/gwmgwroptionsdialog.ui | 3 + src/gwmlcrgwroptionsdialog.cpp | 8 +- src/gwmlcrgwroptionsdialog.ui | 3 + src/gwmmultiscalegwroptionsdialog.cpp | 14 +- src/gwmmultiscalegwroptionsdialog.ui | 3 + src/gwmrobustgwroptionsdialog.cpp | 4 +- src/gwmrobustgwroptionsdialog.ui | 3 + src/gwmswimoptionsdialog.cpp | 6 +- src/gwmswimoptionsdialog.ui | 3 + 44 files changed, 719 insertions(+), 660 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 91b4e47..c3439a3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -49,7 +49,11 @@ include_directories(${QWT_INCLUDE_DIR}) option(ENABLE_OpenMP on) if(ENABLE_OpenMP) - add_definitions(-D ENABLE_OpenMP) + if(MSVC) + set(OpenMP_C_FLAGS "${OpenMP_C_FLAGS} -openmp:llvm") + set(OpenMP_CXX_FLAGS "${OpenMP_CXX_FLAGS} -openmp:llvm") + endif(MSVC) + add_definitions(-D ENABLE_OPENMP) find_package(OpenMP REQUIRED) if(NOT OpenMP_FOUND) message(FATAL_ERROR "OpenMP Not Found!") diff --git a/src/Model/gwmlayerbasicgwritem.cpp b/src/Model/gwmlayerbasicgwritem.cpp index 50900af..f8f7f9a 100644 --- a/src/Model/gwmlayerbasicgwritem.cpp +++ b/src/Model/gwmlayerbasicgwritem.cpp @@ -10,7 +10,7 @@ GwmLayerBasicGWRItem::GwmLayerBasicGWRItem(GwmLayerItem* parent, QgsVectorLayer* mDataPointsSize = taskThread->dataLayer()->featureCount(); mDepVar = taskThread->dependentVariable(); mIndepVars = taskThread->independentVariables(); - mWeight = gwm::BandwidthWeight(*static_cast(taskThread->spatialWeight().weight())); + mWeight = gwm::BandwidthWeight(taskThread->spatialWeight().weight()); mDiagnostic = taskThread->diagnostic(); mDiagnostic0 = taskThread->diagnostic0(); mBetas = mat(taskThread->betas()); diff --git a/src/Model/gwmlayercollinearitygwritem.cpp b/src/Model/gwmlayercollinearitygwritem.cpp index 6d82ef2..63d2e4d 100644 --- a/src/Model/gwmlayercollinearitygwritem.cpp +++ b/src/Model/gwmlayercollinearitygwritem.cpp @@ -9,7 +9,7 @@ GwmLayerCollinearityGWRItem::GwmLayerCollinearityGWRItem(GwmLayerItem* parent, Q mDataPointsSize = taskThread->dataLayer()->featureCount(); mDepVar = taskThread->dependentVariable(); mIndepVars = taskThread->independentVariables(); - mWeight = gwm::BandwidthWeight(*static_cast(taskThread->spatialWeight().weight())); + mWeight = gwm::BandwidthWeight(taskThread->spatialWeight().weight()); mDiagnostic = taskThread->dialnostic(); mDiagnostic0 = taskThread->diagnostic0(); mBetas = mat(taskThread->betas()); diff --git a/src/Model/gwmlayerggwritem.cpp b/src/Model/gwmlayerggwritem.cpp index 04bd4ce..5be4a9a 100644 --- a/src/Model/gwmlayerggwritem.cpp +++ b/src/Model/gwmlayerggwritem.cpp @@ -8,7 +8,7 @@ GwmLayerGGWRItem::GwmLayerGGWRItem(GwmLayerItem* parent, QgsVectorLayer* vector, mDataPointsSize = taskThread->dataLayer()->featureCount(); mDepVar = taskThread->dependentVariable(); mIndepVars = taskThread->independentVariables(); - mWeight = gwm::BandwidthWeight(*static_cast(taskThread->spatialWeight().weight())); + mWeight = gwm::BandwidthWeight(taskThread->spatialWeight().weight()); mBetas = mat(taskThread->betas()); isBandwidthOptimized = taskThread->autoselectBandwidth(); mBandwidthSelScores = taskThread->bandwidthSelectorCriterions(); diff --git a/src/Model/gwmlayergtdritem.cpp b/src/Model/gwmlayergtdritem.cpp index 468a94e..5bcb4a9 100644 --- a/src/Model/gwmlayergtdritem.cpp +++ b/src/Model/gwmlayergtdritem.cpp @@ -42,13 +42,14 @@ GwmLayerGTDRItem::GwmLayerGTDRItem(GwmLayerItem* parentItem, QgsVectorLayer* vec // update mBandwidth if (!sws.empty()) { - auto* optimizedBw = sws[0].weight(); - if (optimizedBw) + const auto& coreW = sws[0].weight(); + if (coreW) { + auto& optimizedBw = sws[0].weight(); // 更新为优化后的带宽值 - mBandwidth->setBandwidth(optimizedBw->bandwidth()); - mBandwidth->setAdaptive(optimizedBw->adaptive()); - mBandwidth->setKernel(static_cast(optimizedBw->kernel())); + mBandwidth->setBandwidth(optimizedBw.bandwidth()); + mBandwidth->setAdaptive(optimizedBw.adaptive()); + mBandwidth->setKernel(static_cast(optimizedBw.kernel())); isBandwidthOptimized = true; } } @@ -57,14 +58,15 @@ GwmLayerGTDRItem::GwmLayerGTDRItem(GwmLayerItem* parentItem, QgsVectorLayer* vec mBandwidths.reserve(sws.size()); for(int i = 0; i < sws.size(); ++i){ // 从 taskMeta 获取初始值,或从优化后的 spatialWeight 获取 - auto* libBw = sws[i].weight(); - if (libBw) + const auto& coreW = sws[i].weight(); + if (coreW) { + auto& libBw = sws[i].weight(); // 创建应用层的带宽权重对象 auto* appBw = new GwmBandwidthWeight( - libBw->bandwidth(), - libBw->adaptive(), - static_cast(libBw->kernel()) + libBw.bandwidth(), + libBw.adaptive(), + static_cast(libBw.kernel()) ); mBandwidths.append(appBw); } diff --git a/src/Model/gwmlayergwpcaitem.cpp b/src/Model/gwmlayergwpcaitem.cpp index 80779e2..9f836cd 100644 --- a/src/Model/gwmlayergwpcaitem.cpp +++ b/src/Model/gwmlayergwpcaitem.cpp @@ -1,4 +1,4 @@ -#include "gwmlayergwpcaitem.h" +#include "gwmlayergwpcaitem.h" #include "gwmlayergroupitem.h" #include @@ -16,14 +16,15 @@ GwmLayerGWPCAItem::GwmLayerGWPCAItem(GwmLayerItem* parent, QgsVectorLayer* vecto mK = taskThread->k(); gwm::SpatialWeight sw = taskThread->spatialWeight(); - gwm::BandwidthWeight* gwmBw = sw.weight(); - if (gwmBw) + const auto& coreW = sw.weight(); + if (coreW) { - if(gwmBw->bandwidth() == 0) + gwm::BandwidthWeight& gwmBw = sw.weight(); + if(gwmBw.bandwidth() == 0) { qDebug() << "[GwmLayerGWPCAItem] WARNING: Bandwidth is 0! This will cause display issues in property panel."; } - mWeight = gwm::BandwidthWeight(*gwmBw); + mWeight = gwm::BandwidthWeight(gwmBw); } else { diff --git a/src/Model/gwmlayerscalablegwritem.cpp b/src/Model/gwmlayerscalablegwritem.cpp index 3548952..182e70d 100644 --- a/src/Model/gwmlayerscalablegwritem.cpp +++ b/src/Model/gwmlayerscalablegwritem.cpp @@ -8,7 +8,7 @@ GwmLayerScalableGWRItem::GwmLayerScalableGWRItem(GwmLayerItem* parent, QgsVector mDataPointsSize = taskThread->dataLayer()->featureCount(); mDepVar = taskThread->dependentVariable(); mIndepVars = taskThread->independentVariables(); - mWeight = gwm::BandwidthWeight(*static_cast(taskThread->spatialWeight().weight())); + mWeight = gwm::BandwidthWeight(taskThread->spatialWeight().weight()); mDistanceType = taskThread->spatialWeight().distance()->type(); mDiagnostic = taskThread->diagnostic(); mDiagnostic0 = taskThread->diagnostic0(); diff --git a/src/TaskThread/gwmbasicgwralgorithm.cpp b/src/TaskThread/gwmbasicgwralgorithm.cpp index 559ac2d..7623bb4 100644 --- a/src/TaskThread/gwmbasicgwralgorithm.cpp +++ b/src/TaskThread/gwmbasicgwralgorithm.cpp @@ -5,6 +5,7 @@ #include #include #include "gwmapp.h" +#include #include using namespace arma; @@ -138,26 +139,23 @@ void GwmBasicGWRAlgorithm::run() if (mIsAutoselectBandwidth) { emit message(QString(tr("Automatically selecting bandwidth ..."))); - qDebug() << "ParallelType in run before =" << mParallelType; - qDebug() << "OmpThreadNum in run before =" << mOmpThreadNum; mGWRCore->setParallelType(mParallelType); mGWRCore->setOmpThreadNum(mOmpThreadNum); - qDebug() << "core parallelType =" << mGWRCore->parallelType(); - qDebug() << "core parallelAbility =" << mGWRCore->parallelAbility(); + qDebug() << "mParallelType:" << static_cast(mParallelType) + << "-> mMGWRCore parallelType:" << static_cast(mGWRCore->parallelType()) + << "parallelAbility:" << static_cast(mGWRCore->parallelAbility()); mGWRCore->setTelegram(std::make_unique(this)); - QElapsedTimer timer; - timer.start(); - + auto start_time = std::chrono::high_resolution_clock::now(); mBetas = mGWRCore->fit(); + auto end_time = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast(end_time - start_time); + qDebug() << "fit() execution time (auto-select bandwidth):" << duration.count() << "ms, Threads:" << mOmpThreadNum; - qint64 elapsed = timer.elapsed(); - qDebug() << "fit() time =" << elapsed << "ms"; - - gwm::BandwidthWeight* bw = mGWRCore->spatialWeight().weight(); + const auto& bw = mGWRCore->spatialWeight().weight(); if (bw && !checkCanceled()) { - mSpatialWeight.setWeight(bw); + mSpatialWeight.setWeight(mGWRCore->spatialWeight().weight()); criterionList = mGWRCore->bandwidthSelectionCriterionList(); QVector> qlist; @@ -166,12 +164,17 @@ void GwmBasicGWRAlgorithm::run() QVariant data = QVariant::fromValue(qlist); emit plot(data, &GwmBandwidthSizeSelector::PlotBandwidthResult); } - // std::cout << "mBetas = \n" << mBetas << std::endl; + std::cout << "mBetas = \n" << mBetas << std::endl; } else { mGWRCore->setParallelType(mParallelType); + mGWRCore->setOmpThreadNum(mOmpThreadNum); + auto start_time = std::chrono::high_resolution_clock::now(); mBetas = mGWRCore->fit(); + auto end_time = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast(end_time - start_time); + qDebug() << "fit() execution time (no auto-select):" << duration.count() << "ms, Threads:" << mOmpThreadNum; } qDebug() << "regression end"; @@ -312,7 +315,7 @@ void GwmBasicGWRAlgorithm::initCuda(IGWmodelCUDA* cuda, const mat& x, const vec& cuda->SetRp(r, mRegressionPoints(r, 0), mRegressionPoints(r, 1)); } } - bool hasDmat = mSpatialWeight.distance()->type() == gwm::Distance::DMatDistance; + bool hasDmat = mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::DMatDistance; if (hasDmat) { for (arma::uword r = 0; r < nRp; r++) @@ -430,25 +433,25 @@ double GwmBasicGWRAlgorithm::indepVarsSelectCriterionCuda(const QListtype() == gwm::Distance::DMatDistance; + bool hasDp = mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::DMatDistance; IGWmodelCUDA* cuda = GWCUDA_Create(nDp, nVar, hasRegressionLayer(), nRp, hasDp); initCuda(cuda, x, y); // 计算参数 double p = 2.0, theta = 0.0; double longlat = false; - if (mSpatialWeight.distance()->type() == gwm::Distance::MinkwoskiDistance) + if (mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::MinkwoskiDistance) { - GwmMinkwoskiDistance* d = mSpatialWeight.distance(); - p = d->poly(); - theta = d->theta(); + gwm::MinkwoskiDistance& d = mSpatialWeight.distance(); + p = d.poly(); + theta = d.theta(); } - else if (mSpatialWeight.distance()->type() == gwm::Distance::CRSDistance) + else if (mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::CRSDistance) { - GwmCRSDistance* d = mSpatialWeight.distance(); - longlat = d->geographic(); + gwm::CRSDistance& d = mSpatialWeight.distance(); + longlat = d.geographic(); } - GwmBandwidthWeight* bw = mSpatialWeight.weight(); - bool gwrStatus = cuda->Regression(true, p, theta, longlat, DBL_MAX, bw->kernel(), bw->adaptive(), mGroupSize, mGpuId); + gwm::BandwidthWeight& bw = mSpatialWeight.weight(); + bool gwrStatus = cuda->Regression(true, p, theta, longlat, DBL_MAX, bw.kernel(), bw.adaptive(), mGroupSize, mGpuId); mat betas(nVar, nDp, fill::zeros); vec shat(2, fill::zeros); double value = DBL_MAX; @@ -537,27 +540,27 @@ mat GwmBasicGWRAlgorithm::regressionOmp(const mat &x, const vec &y) mat GwmBasicGWRAlgorithm::regressionCuda(const mat &x, const vec &y) { int nDp = mDataPoints.n_rows, nVar = x.n_cols, nRp = hasRegressionLayer() ? mRegressionPoints.n_rows : mDataPoints.n_rows; - bool hasDmat = mSpatialWeight.distance()->type() == gwm::Distance::DMatDistance; + bool hasDmat = mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::DMatDistance; IGWmodelCUDA* cuda = GWCUDA_Create(nDp ,nVar, hasRegressionLayer(), nRp, hasDmat); initCuda(cuda, x, y); double p = 2.0, theta = 0.0; double longlat = false; - if (mSpatialWeight.distance()->type() == gwm::Distance::MinkwoskiDistance) + if (mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::MinkwoskiDistance) { - GwmMinkwoskiDistance* d = mSpatialWeight.distance(); - p = d->poly(); - theta = d->theta(); + gwm::MinkwoskiDistance& d = mSpatialWeight.distance(); + p = d.poly(); + theta = d.theta(); } - else if (mSpatialWeight.distance()->type() == gwm::Distance::CRSDistance) + else if (mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::CRSDistance) { - GwmCRSDistance* d = mSpatialWeight.distance(); - longlat = d->geographic(); + gwm::CRSDistance& d = mSpatialWeight.distance(); + longlat = d.geographic(); } int groupSize = mGroupSize; int gpuID = mGpuId; - GwmBandwidthWeight* bw = mSpatialWeight.weight(); - bool adaptive = bw->adaptive(); - bool gwrStatus = cuda->Regression(false, p, theta, longlat, bw->bandwidth(), bw->kernel(), adaptive, groupSize, gpuID); + gwm::BandwidthWeight& bw = mSpatialWeight.weight(); + bool adaptive = bw.adaptive(); + bool gwrStatus = cuda->Regression(false, p, theta, longlat, bw.bandwidth(), bw.kernel(), adaptive, groupSize, gpuID); mat betas(nVar, nRp, fill::zeros); if (gwrStatus) { @@ -667,25 +670,25 @@ mat GwmBasicGWRAlgorithm::regressionHatmatrixOmp(const mat &x, const vec &y, mat mat GwmBasicGWRAlgorithm::regressionHatmatrixCuda(const mat &x, const vec &y, mat &betasSE, vec &shat, vec &qDiag, mat &S) { int nDp = mDataPoints.n_rows, nVar = x.n_cols, nRp = hasRegressionLayer() ? mRegressionPoints.n_rows : mDataPoints.n_rows; - bool hasDmat = mSpatialWeight.distance()->type() == gwm::Distance::DMatDistance; + bool hasDmat = mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::DMatDistance; IGWmodelCUDA* cuda = GWCUDA_Create(nDp ,nVar, hasRegressionLayer(), nRp, hasDmat); initCuda(cuda, x, y); double p = 2.0, theta = 0.0; bool longlat = false; - if (mSpatialWeight.distance()->type() == gwm::Distance::MinkwoskiDistance) + if (mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::MinkwoskiDistance) { - GwmMinkwoskiDistance* d = mSpatialWeight.distance(); - p = d->poly(); - theta = d->theta(); + gwm::MinkwoskiDistance& d = mSpatialWeight.distance(); + p = d.poly(); + theta = d.theta(); } - else if (mSpatialWeight.distance()->type() == gwm::Distance::CRSDistance) + else if (mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::CRSDistance) { - GwmCRSDistance* d = mSpatialWeight.distance(); - longlat = d->geographic(); + gwm::CRSDistance& d = mSpatialWeight.distance(); + longlat = d.geographic(); } - GwmBandwidthWeight* bw = mSpatialWeight.weight(); - bool adaptive = bw->adaptive(); - bool gwrStatus = cuda->Regression(true, p, theta, longlat, bw->bandwidth(), bw->kernel(), adaptive, mGroupSize, mGpuId); + gwm::BandwidthWeight& bw = mSpatialWeight.weight(); + bool adaptive = bw.adaptive(); + bool gwrStatus = cuda->Regression(true, p, theta, longlat, bw.bandwidth(), bw.kernel(), adaptive, mGroupSize, mGpuId); mat betas(nVar, nDp, fill::zeros); betasSE = mat(nVar, nDp, fill::zeros); shat = vec(2, fill::zeros); @@ -837,11 +840,10 @@ double GwmBasicGWRAlgorithm::bandwidthSizeCriterionAICSerial(GwmBandwidthWeight* double GwmBasicGWRAlgorithm::bandwidthSizeCriterionAICOmp(GwmBandwidthWeight *bandwidthWeight) { int nDp = mDataPoints.n_rows, nVar = mIndepVars.size() + 1; - const int selectorStep = static_cast(mBandwidthSizeSelector.bandwidthCriterion().size()); mat betas(nVar, nDp, fill::zeros); mat shat_all(2, mOmpThreadNum, fill::zeros); bool flag = true; - int current = 0; + // int current = 0; #pragma omp parallel for num_threads(mOmpThreadNum) for (int i = 0; i < nDp; i++) { @@ -867,10 +869,10 @@ double GwmBasicGWRAlgorithm::bandwidthSizeCriterionAICOmp(GwmBandwidthWeight *ba flag = false; } // if(mBandwidthSizeSelector.counter<10) - // emit tick(mBandwidthSizeSelector.counter*10 + current * 10 / nDp, 100); - if (selectorStep < 10) - emit tick(selectorStep * 10 + current * 10 / nDp, 100); - current++; + // emit tick(mBandwidthSizeSelector.counter*10 + current * 10 / nDp, 100); + if (i % std::max(1, nDp / 10) == 0) + emit tick(i * 100 / nDp, 100); + // current++; } } if (flag && !checkCanceled()) @@ -896,25 +898,25 @@ double GwmBasicGWRAlgorithm::bandwidthSizeCriterionAICOmp(GwmBandwidthWeight *ba double GwmBasicGWRAlgorithm::bandwidthSizeCriterionAICCuda(GwmBandwidthWeight *bandwidthWeight) { int nDp = mDataPoints.n_rows, nVar = mX.n_cols, nRp = hasRegressionLayer() ? mRegressionPoints.n_rows : mDataPoints.n_rows; - bool hasDmat = mSpatialWeight.distance()->type() == gwm::Distance::DMatDistance; + bool hasDmat = mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::DMatDistance; IGWmodelCUDA* cuda = GWCUDA_Create(nDp ,nVar, hasRegressionLayer(), nRp, hasDmat); initCuda(cuda, mX, mY); double p = 2.0, theta = 0.0; double longlat = false; - if (mSpatialWeight.distance()->type() == gwm::Distance::MinkwoskiDistance) + if (mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::MinkwoskiDistance) { - GwmMinkwoskiDistance* d = mSpatialWeight.distance(); - p = d->poly(); - theta = d->theta(); + gwm::MinkwoskiDistance& d = mSpatialWeight.distance(); + p = d.poly(); + theta = d.theta(); } - else if (mSpatialWeight.distance()->type() == gwm::Distance::CRSDistance) + else if (mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::CRSDistance) { - GwmCRSDistance* d = mSpatialWeight.distance(); - longlat = d->geographic(); + gwm::CRSDistance& d = mSpatialWeight.distance(); + longlat = d.geographic(); } - GwmBandwidthWeight* bw = mSpatialWeight.weight(); - bool adaptive = bw->adaptive(); - bool gwrStatus = cuda->Regression(true, p, theta, longlat, bw->bandwidth(), bw->kernel(), adaptive, mGroupSize, mGpuId); + gwm::BandwidthWeight& bw = mSpatialWeight.weight(); + bool adaptive = bw.adaptive(); + bool gwrStatus = cuda->Regression(true, p, theta, longlat, bw.bandwidth(), bw.kernel(), adaptive, mGroupSize, mGpuId); mat betas(nVar, nDp, fill::zeros); vec shat(2, fill::zeros); double aic = DBL_MAX; @@ -990,11 +992,10 @@ double GwmBasicGWRAlgorithm::bandwidthSizeCriterionCVSerial(GwmBandwidthWeight * double GwmBasicGWRAlgorithm::bandwidthSizeCriterionCVOmp(GwmBandwidthWeight *bandwidthWeight) { int nDp = mDataPoints.n_rows; - const int selectorStep = static_cast(mBandwidthSizeSelector.bandwidthCriterion().size()); vec shat(2, fill::zeros); vec cv_all(mOmpThreadNum, fill::zeros); bool flag = true; - int current = 0; + // int current = 0; #pragma omp parallel for num_threads(mOmpThreadNum) for (int i = 0; i < nDp ; i++) { @@ -1022,10 +1023,10 @@ double GwmBasicGWRAlgorithm::bandwidthSizeCriterionCVOmp(GwmBandwidthWeight *ban flag = false; } // if(mBandwidthSizeSelector.counter<10) - // emit tick(mBandwidthSizeSelector.counter*10 + current * 10 / nDp, 100); - if (selectorStep < 10) - emit tick(selectorStep * 10 + current * 10 / nDp, 100); - current++; + // emit tick(mBandwidthSizeSelector.counter*10 + current * 10 / nDp, 100); + if (i % std::max(1, nDp / 10) == 0) + emit tick(i * 100 / nDp, 100); + // current++; } } if (flag && !checkCanceled()) @@ -1046,21 +1047,21 @@ double GwmBasicGWRAlgorithm::bandwidthSizeCriterionCVOmp(GwmBandwidthWeight *ban double GwmBasicGWRAlgorithm::bandwidthSizeCriterionCVCuda(GwmBandwidthWeight *bandwidthWeight) { int nDp = mDataPoints.n_rows, nVar = mX.n_cols, nRp = hasRegressionLayer() ? mRegressionPoints.n_rows : mDataPoints.n_rows; - bool hasDmat = mSpatialWeight.distance()->type() == gwm::Distance::DMatDistance; + bool hasDmat = mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::DMatDistance; IGWmodelCUDA* cuda = GWCUDA_Create(nDp ,nVar, hasRegressionLayer(), nRp, hasDmat); initCuda(cuda, mX, mY); double p = 2.0, theta = 0.0; double longlat = false; - if (mSpatialWeight.distance()->type() == gwm::Distance::MinkwoskiDistance) + if (mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::MinkwoskiDistance) { - GwmMinkwoskiDistance* d = mSpatialWeight.distance(); - p = d->poly(); - theta = d->theta(); + gwm::MinkwoskiDistance& d = mSpatialWeight.distance(); + p = d.poly(); + theta = d.theta(); } - else if (mSpatialWeight.distance()->type() == gwm::Distance::CRSDistance) + else if (mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::CRSDistance) { - GwmCRSDistance* d = mSpatialWeight.distance(); - longlat = d->geographic(); + gwm::CRSDistance& d = mSpatialWeight.distance(); + longlat = d.geographic(); } bool adaptive = bandwidthWeight->adaptive(); double cv = DBL_MAX; @@ -1289,25 +1290,25 @@ double GwmBasicGWRAlgorithm::calcTrQtQOmp() double GwmBasicGWRAlgorithm::calcTrQtQCuda() { int nDp = mDataPoints.n_rows, nVar = mX.n_cols, nRp = hasRegressionLayer() ? mRegressionPoints.n_rows : mDataPoints.n_rows; - bool hasDmat = mSpatialWeight.distance()->type() == gwm::Distance::DMatDistance; + bool hasDmat = mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::DMatDistance; IGWmodelCUDA* cuda = GWCUDA_Create(nDp ,nVar, hasRegressionLayer(), nRp, hasDmat); initCuda(cuda, mX, mY); double p = 2.0, theta = 0.0; double longlat = false; - if (mSpatialWeight.distance()->type() == gwm::Distance::MinkwoskiDistance) + if (mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::MinkwoskiDistance) { - GwmMinkwoskiDistance* d = mSpatialWeight.distance(); - p = d->poly(); - theta = d->theta(); + gwm::MinkwoskiDistance& d = mSpatialWeight.distance(); + p = d.poly(); + theta = d.theta(); } - else if (mSpatialWeight.distance()->type() == gwm::Distance::CRSDistance) + else if (mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::CRSDistance) { - GwmCRSDistance* d = mSpatialWeight.distance(); - longlat = d->geographic(); + gwm::CRSDistance& d = mSpatialWeight.distance(); + longlat = d.geographic(); } - GwmBandwidthWeight* bw = mSpatialWeight.weight(); - bool adaptive = bw->adaptive(); - double trQtQ = cuda->CalcTrQtQ(p, theta, longlat, bw->bandwidth(), bw->kernel(), adaptive, mGroupSize, mGpuId); + gwm::BandwidthWeight& bw = mSpatialWeight.weight(); + bool adaptive = bw.adaptive(); + double trQtQ = cuda->CalcTrQtQ(p, theta, longlat, bw.bandwidth(), bw.kernel(), adaptive, mGroupSize, mGpuId); GWCUDA_Del(cuda); return trQtQ; } @@ -1401,26 +1402,26 @@ vec GwmBasicGWRAlgorithm::calcDiagBOmp(int i) vec GwmBasicGWRAlgorithm::calcDiagBCuda(int i) { int nDp = mDataPoints.n_rows, nVar = mX.n_cols, nRp = hasRegressionLayer() ? mRegressionPoints.n_rows : mDataPoints.n_rows; - bool hasDmat = mSpatialWeight.distance()->type() == gwm::Distance::DMatDistance; + bool hasDmat = mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::DMatDistance; IGWmodelCUDA* cuda = GWCUDA_Create(nDp ,nVar, hasRegressionLayer(), nRp, hasDmat); initCuda(cuda, mX, mY); double p = 2.0, theta = 0.0; double longlat = false; - if (mSpatialWeight.distance()->type() == gwm::Distance::MinkwoskiDistance) + if (mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::MinkwoskiDistance) { - GwmMinkwoskiDistance* d = mSpatialWeight.distance(); - p = d->poly(); - theta = d->theta(); + gwm::MinkwoskiDistance& d = mSpatialWeight.distance(); + p = d.poly(); + theta = d.theta(); } - else if (mSpatialWeight.distance()->type() == gwm::Distance::CRSDistance) + else if (mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::CRSDistance) { - GwmCRSDistance* d = mSpatialWeight.distance(); - longlat = d->geographic(); + gwm::CRSDistance& d = mSpatialWeight.distance(); + longlat = d.geographic(); } - GwmBandwidthWeight* bw = mSpatialWeight.weight(); - bool adaptive = bw->adaptive(); + gwm::BandwidthWeight& bw = mSpatialWeight.weight(); + bool adaptive = bw.adaptive(); vec diagB(2, fill::zeros); - bool status = cuda->CalcB(i, p, theta, longlat, bw->bandwidth(), bw->kernel(), adaptive, mGroupSize, mGpuId); + bool status = cuda->CalcB(i, p, theta, longlat, bw.bandwidth(), bw.kernel(), adaptive, mGroupSize, mGpuId); if (status) { diagB = { cuda->GetTrB(), cuda->GetTrBdB() }; @@ -1443,8 +1444,8 @@ bool GwmBasicGWRAlgorithm::isValid() if (!mIsAutoselectBandwidth) { - gwm::BandwidthWeight* bw = mSpatialWeight.weight(); - if (bw->adaptive() && bw->bandwidth() <= mIndepVars.size()) + gwm::BandwidthWeight& bw = mSpatialWeight.weight(); + if (bw.adaptive() && bw.bandwidth() <= static_cast(mIndepVars.size())) return false; } return true; @@ -1458,23 +1459,17 @@ void GwmBasicGWRAlgorithm::initPoints() if (!hasRegressionLayer() && !mHasHatMatrix) { mRegressionPoints = mDataPoints; - if (mSpatialWeight.distance()->type() == gwm::Distance::CRSDistance || mSpatialWeight.distance()->type() == gwm::Distance::MinkwoskiDistance) + if (mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::CRSDistance || mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::MinkwoskiDistance) { - if (mSpatialWeight.distance()->type() == gwm::Distance::CRSDistance) + if (mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::CRSDistance) { - auto *d = mSpatialWeight.distance(); - if (d) - { - d->makeParameter({ mRegressionPoints, mDataPoints }); - } + auto &d = mSpatialWeight.distance(); + d.makeParameter({ mRegressionPoints, mDataPoints }); } - else if (mSpatialWeight.distance()->type() == gwm::Distance::MinkwoskiDistance) + else if (mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::MinkwoskiDistance) { - auto *d2 = mSpatialWeight.distance(); - if (d2) - { - d2->makeParameter({ mRegressionPoints, mDataPoints }); - } + auto &d2 = mSpatialWeight.distance(); + d2.makeParameter({ mRegressionPoints, mDataPoints }); } } } @@ -1547,6 +1542,6 @@ void GwmBasicGWRAlgorithm::setBandwidthSelectionCriterionType(const gwm::GWRBasi void GwmBasicGWRAlgorithm::setParallelType(const gwm::ParallelType &type) { - // mParallelType = type; - // mGWRCore->setParallelType(type); + mParallelType = type; + mGWRCore->setParallelType(type); } diff --git a/src/TaskThread/gwmbasicgwralgorithm.h b/src/TaskThread/gwmbasicgwralgorithm.h index 2e23c71..02e9e7e 100644 --- a/src/TaskThread/gwmbasicgwralgorithm.h +++ b/src/TaskThread/gwmbasicgwralgorithm.h @@ -165,7 +165,7 @@ class GwmBasicGWRAlgorithm : public GwmGeographicalWeightedRegressionAlgorithm, rowvec distanceParam1(int i) { - return (mSpatialWeight.distance()->type() == gwm::Distance::DMatDistance ? vec(1).fill(i) : mDataPoints.row(i)); + return (mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::DMatDistance ? vec(1).fill(i) : mDataPoints.row(i)); } protected: void OLS(); @@ -248,7 +248,7 @@ class GwmBasicGWRAlgorithm : public GwmGeographicalWeightedRegressionAlgorithm, vec mRegressionLayerY; mat mRegressionLayerX; - gwm::BandwidthSelector mBandwidthSizeSelector; + //gwm::BandwidthSelector mBandwidthSizeSelector; gwm::BandwidthCriterionList criterionList; bool mIsAutoselectBandwidth = false; gwm::GWRBasic::BandwidthSelectionCriterionType mBandwidthSelectionCriterionType = gwm::GWRBasic::BandwidthSelectionCriterionType::AIC; diff --git a/src/TaskThread/gwmgeneralizedgwralgorithm.cpp b/src/TaskThread/gwmgeneralizedgwralgorithm.cpp index 70ff44c..106c4f7 100644 --- a/src/TaskThread/gwmgeneralizedgwralgorithm.cpp +++ b/src/TaskThread/gwmgeneralizedgwralgorithm.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #ifdef ENABLE_OpenMP #include @@ -95,7 +96,14 @@ void GwmGeneralizedGWRAlgorithm::run() if (mIsAutoselectBandwidth) { emit message(QString(tr("Automatically selecting bandwidth ..."))); + qDebug() << "mParallelType:" << static_cast(mParallelType) + << "-> mGGWRCore parallelType:" << static_cast(mGGWRCore->parallelType()) + << "parallelAbility:" << static_cast(mGGWRCore->parallelAbility()); + auto start_time = std::chrono::high_resolution_clock::now(); mBetas = mGGWRCore->fit(); + auto end_time = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast(end_time - start_time); + qDebug() << "fit() execution time (auto-select bandwidth):" << duration.count() << "ms, Threads:" << mOmpThreadNum; // if(mHasHatMatrix) // { // arma::mat tempS; @@ -106,13 +114,15 @@ void GwmGeneralizedGWRAlgorithm::run() // mBetas = mGGWRCore->fit(); // } - gwm::BandwidthWeight* bw = mGGWRCore->spatialWeight().weight(); - emit message(tr("bandwidth selected: %1").arg(bw->bandwidth())); - if (bw && !checkCanceled()) + const auto &coreW = mGGWRCore->spatialWeight().weight(); + if (coreW && !checkCanceled()) { + gwm::BandwidthWeight& bw = mGGWRCore->spatialWeight().weight(); + emit message(tr("bandwidth selected: %1").arg(bw.bandwidth())); + mSpatialWeight.setWeight(bw); - criterionList = mGGWRCore->mBandwidthSelectionCriterionList; + criterionList = mGGWRCore->bandwidthSelectorCriterions(); // 绘图数据 QVector> qlist; @@ -125,13 +135,24 @@ void GwmGeneralizedGWRAlgorithm::run() else { emit message(QString(tr("Fitting GGWR model..."))); + qDebug() << "mParallelType:" << static_cast(mParallelType) + << "-> mGGWRCore parallelType:" << static_cast(mGGWRCore->parallelType()) + << "parallelAbility:" << static_cast(mGGWRCore->parallelAbility()); + auto start_time = std::chrono::high_resolution_clock::now(); mBetas = mGGWRCore->fit(); + auto end_time = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast(end_time - start_time); + qDebug() << "fit() execution time (no auto-select):" << duration.count() << "ms, Threads:" << mOmpThreadNum; } } else if (!checkCanceled() && hasRegressionLayer()) { emit message(QString(tr("Fitting GGWR model..."))); + auto start_time = std::chrono::high_resolution_clock::now(); mBetas = mGGWRCore->fit(); + auto end_time = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast(end_time - start_time); + qDebug() << "fit() execution time (regression layer):" << duration.count() << "ms, Threads:" << mOmpThreadNum; } // 优选带宽 @@ -139,7 +160,7 @@ void GwmGeneralizedGWRAlgorithm::run() // { // emit message(QString(tr("Automatically selecting bandwidth ..."))); // //emit tick(0, 0); - // if ((mSpatialWeight.distance()->type() == gwm::Distance::CRSDistance || mSpatialWeight.distance()->type() == gwm::Distance::MinkwoskiDistance) && !checkCanceled()) + // if ((mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::CRSDistance || mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::MinkwoskiDistance) && !checkCanceled()) // { // gwm::CRSDistance* d = static_cast(mSpatialWeight.distance()); // d->makeParameter({ mDataPoints, mDataPoints }); @@ -162,7 +183,7 @@ void GwmGeneralizedGWRAlgorithm::run() // QVariant data = QVariant::fromValue(mBandwidthSizeSelector.bandwidthCriterion()); // emit plot(data, &GwmBandwidthSizeSelector::PlotBandwidthResult); // } - // if ((mSpatialWeight.distance()->type() == gwm::Distance::CRSDistance || mSpatialWeight.distance()->type() == gwm::Distance::MinkwoskiDistance) && !checkCanceled()) + // if ((mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::CRSDistance || mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::MinkwoskiDistance) && !checkCanceled()) // { // gwm::CRSDistance* d = static_cast(mSpatialWeight.distance()); // d->makeParameter({ mDataPoints, mDataPoints }); @@ -194,7 +215,7 @@ void GwmGeneralizedGWRAlgorithm::run() // mWtMat2.col(i) = weight; // emit tick(i, nRp); // } - // if ((mSpatialWeight.distance()->type() == gwm::Distance::CRSDistance || mSpatialWeight.distance()->type() == gwm::Distance::MinkwoskiDistance) && !checkCanceled()) + // if ((mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::CRSDistance || mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::MinkwoskiDistance) && !checkCanceled()) // { // gwm::CRSDistance* d = static_cast(mSpatialWeight.distance()); // d->makeParameter({ mDataPoints, mDataPoints }); @@ -589,7 +610,7 @@ mat GwmGeneralizedGWRAlgorithm::regressionPoissonOmp(const mat &x, const vec &y) mat S(isStoreS ? nDp : 1, nDp, fill::zeros); int current = 0; if(mHasHatMatrix && !checkCanceled()){ - mat shat = mat(2,mOmpThreadNum,fill::zeros); + mat shat = mat(2,mOmpThreadNum,fill::zeros); #pragma omp parallel for num_threads(mOmpThreadNum) for(int i = 0; i < nDp; i++){ mat ci,s_ri; @@ -818,7 +839,7 @@ double GwmGeneralizedGWRAlgorithm::bandwidthSizeGGWRCriterionCVSerial(GwmBandwid .arg(res); emit message(msg); return res; - } + } else return DBL_MAX; } @@ -828,8 +849,7 @@ double GwmGeneralizedGWRAlgorithm::bandwidthSizeGGWRCriterionCVOmp(GwmBandwidthW int n = mDataPoints.n_rows; vec cv = vec(n); mat wt = mat(n,n); - int current1 = 0, current2 = 0; - const int selectorStep = static_cast(mBandwidthSizeSelector.bandwidthCriterion().size()); + // int current1 = 0, current2 = 0; #pragma omp parallel for num_threads(mOmpThreadNum) for (int i = 0; i < n; i++) { @@ -840,10 +860,10 @@ double GwmGeneralizedGWRAlgorithm::bandwidthSizeGGWRCriterionCVOmp(GwmBandwidthW w.row(i) = 0; wt.col(i) = w; // if(mBandwidthSizeSelector.counter<10) - // emit tick(mBandwidthSizeSelector.counter*10 + current2 * 5 / n + 5, 100); - if (selectorStep < 10) - emit tick(selectorStep * 10 + current2 * 5 / n + 5, 100); - current2++; + // emit tick(mBandwidthSizeSelector.counter*10 + current1 * 5 / n, 100); + if (i % std::max(1, n / 10) == 0) + emit tick(i * 100 / n, 100); + // current1++; } } if (!checkCanceled()) (this->*mCalWtFunction)(mX,mY,wt); @@ -861,10 +881,10 @@ double GwmGeneralizedGWRAlgorithm::bandwidthSizeGGWRCriterionCVOmp(GwmBandwidthW cv.row(i) = mY.row(i) - exp(yhatnoi)/(1+exp(yhatnoi)); } // if(mBandwidthSizeSelector.counter<10) - // emit tick(mBandwidthSizeSelector.counter*10 + current2 * 5 / n + 5, 100); - if (selectorStep < 10) - emit tick(selectorStep * 10 + current2 * 5 / n + 5, 100); - current2++; + // emit tick(mBandwidthSizeSelector.counter*10 + current2 * 5 / n + 5, 100); + if (i % std::max(1, n / 10) == 0) + emit tick(i * 100 / n, 100); + // current2++; } } vec cvsquare = trans(cv) * cv ; @@ -888,7 +908,7 @@ double GwmGeneralizedGWRAlgorithm::bandwidthSizeGGWRCriterionAICSerial(GwmBandwi int n = mDataPoints.n_rows; vec cv = vec(n); mat S = mat(n,n); - mat wt = mat(n,n); + mat wt = mat(n,n); for (int i = 0; i < n && !checkCanceled(); i++) { vec d = mSpatialWeight.distance()->distance(i); @@ -939,8 +959,7 @@ double GwmGeneralizedGWRAlgorithm::bandwidthSizeGGWRCriterionAICOmp(GwmBandwidth vec cv = vec(n); mat S = mat(n,n); mat wt = mat(n,n); - int current1 = 0, current2 = 0; - const int selectorStep = static_cast(mBandwidthSizeSelector.bandwidthCriterion().size()); + // int current1 = 0, current2 = 0; #pragma omp parallel for num_threads(mOmpThreadNum) for (int i = 0; i < n; i++) { @@ -950,10 +969,10 @@ double GwmGeneralizedGWRAlgorithm::bandwidthSizeGGWRCriterionAICOmp(GwmBandwidth vec w = bandwidthWeight->weight(d); wt.col(i) = w; // if(mBandwidthSizeSelector.counter<10) - // emit tick(mBandwidthSizeSelector.counter*10 + current1 * 5 / n, 100); - if (selectorStep < 10) - emit tick(selectorStep * 10 + current1 * 5 / n, 100); - current1++; + // emit tick(mBandwidthSizeSelector.counter*10 + current1 * 5 / n, 100); + if (i % std::max(1, n / 10) == 0) + emit tick(i * 100 / n, 100); + // current1++; } } if (!checkCanceled()) (this->*mCalWtFunction)(mX,mY,wt); @@ -969,9 +988,9 @@ double GwmGeneralizedGWRAlgorithm::bandwidthSizeGGWRCriterionAICOmp(GwmBandwidth trS(thread) += S(i,i); // if(mBandwidthSizeSelector.counter<10) // emit tick(mBandwidthSizeSelector.counter*10 + current2 * 5 / n + 5, 100); - if (selectorStep < 10) - emit tick(selectorStep * 10 + current2 * 5 / n + 5, 100); - current2++; + if (i % std::max(1, n / 10) == 0) + emit tick(i * 100 / n, 100); + // current2++; } } double AICc; @@ -1217,30 +1236,28 @@ void GwmGeneralizedGWRAlgorithm::createResultLayer(CreateResultLayerData data,QS void GwmGeneralizedGWRAlgorithm::setBandwidthSelectionCriterionType(const BandwidthSelectionCriterionType &bandwidthSelectionCriterionType) { - mBandwidthSelectionCriterionType = bandwidthSelectionCriterionType; - QMap, BandwidthSelectCriterionFunction> mapper = { - std::make_pair(qMakePair(BandwidthSelectionCriterionType::CV, gwm::ParallelType::SerialOnly), &GwmGeneralizedGWRAlgorithm::bandwidthSizeGGWRCriterionCVSerial), - #ifdef ENABLE_OpenMP - std::make_pair(qMakePair(BandwidthSelectionCriterionType::CV, gwm::ParallelType::OpenMP), &GwmGeneralizedGWRAlgorithm::bandwidthSizeGGWRCriterionCVOmp), - #endif - std::make_pair(qMakePair(BandwidthSelectionCriterionType::CV, gwm::ParallelType::CUDA), &GwmGeneralizedGWRAlgorithm::bandwidthSizeGGWRCriterionCVSerial), - std::make_pair(qMakePair(BandwidthSelectionCriterionType::AIC, gwm::ParallelType::SerialOnly), &GwmGeneralizedGWRAlgorithm::bandwidthSizeGGWRCriterionAICSerial), - #ifdef ENABLE_OpenMP - std::make_pair(qMakePair(BandwidthSelectionCriterionType::AIC, gwm::ParallelType::OpenMP), &GwmGeneralizedGWRAlgorithm::bandwidthSizeGGWRCriterionAICOmp), - #endif - std::make_pair(qMakePair(BandwidthSelectionCriterionType::AIC, gwm::ParallelType::CUDA), &GwmGeneralizedGWRAlgorithm::bandwidthSizeGGWRCriterionAICSerial) - }; - mBandwidthSelectCriterionFunction = mapper[qMakePair(bandwidthSelectionCriterionType, mParallelType)]; + // mBandwidthSelectionCriterionType = bandwidthSelectionCriterionType; + // QMap, BandwidthSelectCriterionFunction> mapper = { + // std::make_pair(qMakePair(BandwidthSelectionCriterionType::CV, gwm::ParallelType::SerialOnly), &GwmGeneralizedGWRAlgorithm::bandwidthSizeGGWRCriterionCVSerial), + // #ifdef ENABLE_OpenMP + // std::make_pair(qMakePair(BandwidthSelectionCriterionType::CV, gwm::ParallelType::OpenMP), &GwmGeneralizedGWRAlgorithm::bandwidthSizeGGWRCriterionCVOmp), + // #endif + // std::make_pair(qMakePair(BandwidthSelectionCriterionType::CV, gwm::ParallelType::CUDA), &GwmGeneralizedGWRAlgorithm::bandwidthSizeGGWRCriterionCVSerial), + // std::make_pair(qMakePair(BandwidthSelectionCriterionType::AIC, gwm::ParallelType::SerialOnly), &GwmGeneralizedGWRAlgorithm::bandwidthSizeGGWRCriterionAICSerial), + // #ifdef ENABLE_OpenMP + // std::make_pair(qMakePair(BandwidthSelectionCriterionType::AIC, gwm::ParallelType::OpenMP), &GwmGeneralizedGWRAlgorithm::bandwidthSizeGGWRCriterionAICOmp), + // #endif + // std::make_pair(qMakePair(BandwidthSelectionCriterionType::AIC, gwm::ParallelType::CUDA), &GwmGeneralizedGWRAlgorithm::bandwidthSizeGGWRCriterionAICSerial) + // }; + // mBandwidthSelectCriterionFunction = mapper[qMakePair(bandwidthSelectionCriterionType, mParallelType)]; } void GwmGeneralizedGWRAlgorithm::setParallelType(const gwm::ParallelType &type) { - if (type & parallelAbility()) - { - mParallelType = type; - setBandwidthSelectionCriterionType(mBandwidthSelectionCriterionType); - setFamily(mFamily); - } + mParallelType = type; + mGGWRCore->setParallelType(type); + setBandwidthSelectionCriterionType(mBandwidthSelectionCriterionType); + setFamily(mFamily); } mat GwmGeneralizedGWRAlgorithm::diag(mat a){ @@ -1470,11 +1487,11 @@ void GwmGeneralizedGWRAlgorithm::fTest(FTestParameters params) f3.append(f3i); continue; } - + double g1 = diagB(0); double g2 = diagB(1); double numdf = g1 * g1 / g2; - + // 检查计算结果的有效性 if (g1 <= 0 || g2 <= 0 || numdf <= 0 || !isfinite(numdf)) { @@ -1486,7 +1503,7 @@ void GwmGeneralizedGWRAlgorithm::fTest(FTestParameters params) f3.append(f3i); continue; } - + GwmFTestResult f3i; f3i.s = (vk2(i) / g1) / sigma2delta1; f3i.df1 = numdf; @@ -1526,20 +1543,20 @@ vec GwmGeneralizedGWRAlgorithm::calcDiagBSerial(int i) arma::uword nDp = mX.n_rows, nVar = mX.n_cols; vec diagB(nDp, fill::zeros), c(nDp, fill::zeros); mat wspan(1, nVar, fill::ones); - + // 第一遍循环:计算 c(所有数据点的系数矩阵第 i 列的平均值) for (arma::uword j = 0; j < nDp && !checkCanceled(); j++) { vec wj = mWtMat2.col(j); vec weights = wj % mWt2; - + // 检查权重有效性 if (sum(weights) < 1e-10 || any(weights < 0) || !weights.is_finite()) { emit error("Invalid weights in calcDiagB (first loop)."); return { DBL_MAX, DBL_MAX }; } - + mat xtw = trans(mX % (weights * wspan)); try { // 使用 inv_sympd 替代 pinv,与 BasicGWR 保持一致 @@ -1550,20 +1567,20 @@ vec GwmGeneralizedGWRAlgorithm::calcDiagBSerial(int i) return { DBL_MAX, DBL_MAX }; } } - + // 第二遍循环:计算 diagB for (arma::uword k = 0; k < nDp && !checkCanceled(); k++) { vec wk = mWtMat2.col(k); vec weights = wk % mWt2; - + // 检查权重有效性 if (sum(weights) < 1e-10 || any(weights < 0) || !weights.is_finite()) { emit error("Invalid weights in calcDiagB (second loop)."); return { DBL_MAX, DBL_MAX }; } - + mat xtw = trans(mX % (weights * wspan)); try { // 使用 inv_sympd 替代 pinv,与 BasicGWR 保持一致 @@ -1575,7 +1592,7 @@ vec GwmGeneralizedGWRAlgorithm::calcDiagBSerial(int i) return { DBL_MAX, DBL_MAX }; } } - + diagB = 1.0 / nDp * diagB; return { sum(diagB), sum(diagB % diagB) }; } diff --git a/src/TaskThread/gwmgeneralizedgwralgorithm.h b/src/TaskThread/gwmgeneralizedgwralgorithm.h index b154e8a..40ba91a 100644 --- a/src/TaskThread/gwmgeneralizedgwralgorithm.h +++ b/src/TaskThread/gwmgeneralizedgwralgorithm.h @@ -120,7 +120,10 @@ class GwmGeneralizedGWRAlgorithm : public GwmGeographicalWeightedRegressionAlgor public: double criterionLib(gwm::BandwidthWeight* bandwidthWeight){ double criterionValue = 0.0; - mGGWRCore->getCriterion(bandwidthWeight, criterionValue); + auto cloned = bandwidthWeight->clone(); + std::unique_ptr bw( + static_cast(cloned.release())); + mGGWRCore->getCriterion(bw, criterionValue); return criterionValue; } @@ -266,7 +269,7 @@ class GwmGeneralizedGWRAlgorithm : public GwmGeographicalWeightedRegressionAlgor bool mIsAutoselectBandwidth = false; BandwidthSelectionCriterionType mBandwidthSelectionCriterionType = BandwidthSelectionCriterionType::AIC; BandwidthSelectCriterionFunction mBandwidthSelectCriterionFunction = &GwmGeneralizedGWRAlgorithm::bandwidthSizeGGWRCriterionCVSerial; - gwm::BandwidthSelector mBandwidthSizeSelector; + //gwm::BandwidthSelector mBandwidthSizeSelector; gwm::ParallelType mParallelType = gwm::ParallelType::SerialOnly; int mOmpThreadNum = 8; diff --git a/src/TaskThread/gwmgeographicalweightedregressionalgorithm.cpp b/src/TaskThread/gwmgeographicalweightedregressionalgorithm.cpp index 4cc63d1..4c52e3e 100644 --- a/src/TaskThread/gwmgeographicalweightedregressionalgorithm.cpp +++ b/src/TaskThread/gwmgeographicalweightedregressionalgorithm.cpp @@ -49,23 +49,17 @@ void GwmGeographicalWeightedRegressionAlgorithm::initPoints() } else mRegressionPoints = mDataPoints; // 设置空间距离中的数据指针 - if (mSpatialWeight.distance()->type() == gwm::Distance::CRSDistance || mSpatialWeight.distance()->type() == gwm::Distance::MinkwoskiDistance) + if (mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::CRSDistance || mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::MinkwoskiDistance) { - if (mSpatialWeight.distance()->type() == gwm::Distance::CRSDistance) + if (mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::CRSDistance) { - auto *d = mSpatialWeight.distance(); - if (d) - { - d->makeParameter({ mRegressionPoints, mDataPoints }); - } + auto &d = mSpatialWeight.distance(); + d.makeParameter({ mRegressionPoints, mDataPoints }); } - else if (mSpatialWeight.distance()->type() == gwm::Distance::MinkwoskiDistance) + else if (mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::MinkwoskiDistance) { - auto *d2 = mSpatialWeight.distance(); - if (d2) - { - d2->makeParameter({ mRegressionPoints, mDataPoints }); - } + auto &d2 = mSpatialWeight.distance(); + d2.makeParameter({ mRegressionPoints, mDataPoints }); } } diff --git a/src/TaskThread/gwmgtdrtaskthread.cpp b/src/TaskThread/gwmgtdrtaskthread.cpp index c5087e0..367bf81 100644 --- a/src/TaskThread/gwmgtdrtaskthread.cpp +++ b/src/TaskThread/gwmgtdrtaskthread.cpp @@ -2,9 +2,11 @@ #include #include #include "SpatialWeight/gwmcrsdistance.h" +#include #ifdef ENABLE_OpenMP #include #endif +#include using namespace std; using namespace gwm; @@ -262,14 +264,16 @@ void GwmGTDRTaskThread::run() int nWeightingVars = mMeta.weightingVariables.size(); for (arma::uword k = 0; k < nWeightingVars && k < mWeightingData.n_cols; ++k) { - auto* od = sws[k].distance(); - if (!od) { - emit error(tr("GTDR invalid: spatialWeights[%1] is not OneDimDistance.").arg(int(k))); + const auto &distH = sws[k].distance(); + if (!distH) + { + emit error(tr("GTDR invalid: spatialWeights[%1] has null distance.").arg(int(k))); return; } + auto &od = sws[k].distance(); // 使用权重变量的第k列来设置距离参数 arma::vec col = mWeightingData.col(k); - od->makeParameter({ col, col }); + od.makeParameter({ col, col }); emit message(tr("Distance parameter set for weighting variable: %1") .arg(mMeta.weightingVariables[k].name)); } @@ -278,13 +282,15 @@ void GwmGTDRTaskThread::run() if (hasTimeStamp && sws.size() > nWeightingVars && mWeightingData.n_cols > nWeightingVars) { arma::uword timeStampIndex = nWeightingVars; - auto* od = sws[timeStampIndex].distance(); - if (!od) { - emit error(tr("GTDR invalid: spatialWeights[%1] (timestamp) is not OneDimDistance.").arg(int(timeStampIndex))); + const auto &distH = sws[timeStampIndex].distance(); + if (!distH) + { + emit error(tr("GTDR invalid: spatialWeights[%1] (timestamp) has null distance.").arg(int(timeStampIndex))); return; } + auto &od = sws[timeStampIndex].distance(); arma::vec col = mWeightingData.col(timeStampIndex); - od->makeParameter({ col, col }); + od.makeParameter({ col, col }); emit message(tr("Distance parameter set for timestamp variable: %1") .arg(mMeta.timeStampVariable.name)); } @@ -295,28 +301,30 @@ void GwmGTDRTaskThread::run() { // Bandwidth size selection emit message(tr("Automatically selecting bandwidth...")); - vector vecBandwidthWeight0 ; + // vector vecBandwidthWeight0 ; mAlgorithm.setBandwidthCriterionType(mMeta.bandwidthCriterionType); // 4. 收集所有维度的带宽权重指针 - std::vector bandwidths; + // std::vector bandwidths; + std::vector> bandwidths; const auto& sws = mAlgorithm.spatialWeights(); for (const auto& sw : sws) { - auto* bw = sw.weight(); - if (bw) + const auto &wH = sw.weight(); + if (wH) { + gwm::BandwidthWeight &bw = sw.weight(); bandwidths.push_back(bw); // 设置初始带宽值(如果当前值不合理) - double lower = bw->adaptive() ? (mIndepVars.size() + 1) : 0.0; - double upper = bw->adaptive() ? mX.n_rows : sw.distance()->maxDistance(); - if (bw->bandwidth() <= lower || bw->bandwidth() >= upper || !isfinite(bw->bandwidth())) + double lower = bw.adaptive() ? (mIndepVars.size() + 1) : 0.0; + double upper = bw.adaptive() ? mX.n_rows : sw.distance()->maxDistance(); + if (bw.bandwidth() <= lower || bw.bandwidth() >= upper || !isfinite(bw.bandwidth())) { - double initBw = bw->adaptive() + double initBw = bw.adaptive() ? std::max(20.0, upper * 0.618) : upper * 0.618; - bw->setBandwidth(initBw); + bw.setBandwidth(initBw); } } } @@ -362,15 +370,16 @@ void GwmGTDRTaskThread::run() const auto& sws = mAlgorithm.spatialWeights(); for (size_t i = 0; i < sws.size(); ++i) { - auto* bw = sws[i].weight(); - if (bw) + const auto &wHi = sws[i].weight(); + if (wHi) { + auto& bw = sws[i].weight(); QString varName = i < mMeta.weightingVariables.size() ? mMeta.weightingVariables[i].name : QString("Dimension_%1").arg(i); emit message(tr("Dimension %1 (%2): optimized bandwidth = %3") - .arg(i).arg(varName).arg(bw->bandwidth())); + .arg(i).arg(varName).arg(bw.bandwidth())); } } } @@ -381,25 +390,26 @@ void GwmGTDRTaskThread::run() const auto& sws = mAlgorithm.spatialWeights(); for (size_t i = 0; i < sws.size(); ++i) { - auto* bw = sws[i].weight(); - if (bw) + const auto &wHi = sws[i].weight(); + if (wHi) { + auto& bw = sws[i].weight(); //bw->setBandwidth(100);// 继续使用初始带宽值(这里需要实时更新) // 直接使用 bandwidths 中的当前值(优化器最后一次尝试的值) - double currentBw = bandwidths[i]->bandwidth(); + double currentBw = bandwidths[i].get().bandwidth(); // 验证值的有效性 - double lower = bw->adaptive() ? (mMeta.weightingVariables.size() + 1) : 0.0; - double upper = bw->adaptive() ? mX.n_rows : sws[i].distance()->maxDistance(); + double lower = bw.adaptive() ? (mMeta.weightingVariables.size() + 1) : 0.0; + double upper = bw.adaptive() ? mX.n_rows : sws[i].distance()->maxDistance(); if (currentBw <= lower || currentBw >= upper || !isfinite(currentBw)) { // 如果值无效,使用合理的默认值 - currentBw = bw->adaptive() + currentBw = bw.adaptive() ? std::round(std::max(20.0, upper * 0.618)) : upper * 0.618; - bw->setBandwidth(currentBw); + bw.setBandwidth(currentBw); } // 如果值有效,不需要设置(已经是当前值) @@ -408,7 +418,7 @@ void GwmGTDRTaskThread::run() : QString("Dimension_%1").arg(i); emit message(tr("Dimension %1 (%2): using initial bandwidth: %3 (optimization failed)") - .arg(i).arg(varName).arg(bw->bandwidth())); + .arg(i).arg(varName).arg(bw.bandwidth())); } } } @@ -433,9 +443,20 @@ void GwmGTDRTaskThread::run() if (checkCanceled()) return; try { + // Ensure algorithm parallel settings reflect UI/meta + mAlgorithm.setParallelType(mMeta.parallelType); + mAlgorithm.setOmpThreadNum(mMeta.parallelOmpThreads); + qDebug() << "mParallelType:" << static_cast(mMeta.parallelType) + << "-> mAlgorithm parallelType:" << static_cast(mAlgorithm.parallelType()) + << "parallelAbility:" << static_cast(mAlgorithm.parallelAbility()); + + auto start_time = std::chrono::high_resolution_clock::now(); mAlgorithm.fit(); - emit message(tr("fit.")); - + auto end_time = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast(end_time - start_time); + qDebug() << "GTDR fit() execution time:" << duration.count() << "ms, Threads:" << mMeta.parallelOmpThreads; + emit message(tr("fit completed in %1 ms").arg(QString::number(duration.count()))); + mDiagnostic=mAlgorithm.diagnostic(); mBetas = mAlgorithm.betas(); mBetasSE = mAlgorithm.betasSE(); diff --git a/src/TaskThread/gwmgtdrtaskthread.h b/src/TaskThread/gwmgtdrtaskthread.h index f5404d9..0fed0a7 100644 --- a/src/TaskThread/gwmgtdrtaskthread.h +++ b/src/TaskThread/gwmgtdrtaskthread.h @@ -107,7 +107,7 @@ class GwmGTDRTaskThread : public GwmSpatialAlgorithm, public IOpenmpParallelable std::vector> mBandwidthHolders; std::vector> mDistanceHolders; - gwm::BandwidthSelector mBandwidthSizeSelector; + //gwm::BandwidthSelector mBandwidthSizeSelector; //gwm::GTDRBandwidthOptimizer mGTDRBandwidthOptimizer; int mCurrentOptimizingDim = -1; diff --git a/src/TaskThread/gwmgtwralgorithm.cpp b/src/TaskThread/gwmgtwralgorithm.cpp index 2633ada..e9aeb5f 100644 --- a/src/TaskThread/gwmgtwralgorithm.cpp +++ b/src/TaskThread/gwmgtwralgorithm.cpp @@ -3,6 +3,7 @@ #include #endif #include +#include int GwmGTWRAlgorithm::treeChildCount = 0; GwmDiagnostic GwmGTWRAlgorithm::CalcDiagnostic(const mat &x, const vec &y, const mat &betas, const vec &shat) @@ -75,15 +76,24 @@ void GwmGTWRAlgorithm::run() { emit message(QString(tr("Automatically selecting bandwidth ..."))); emit tick(0, 0); - mGTWRCore->setParallelType(static_cast(mParallelType)); + mGTWRCore->setParallelType(mParallelType); + mGTWRCore->setOmpThreadNum(mOmpThreadNum); mGTWRCore->setTelegram(std::make_unique(this)); + qDebug() << "mParallelType:" << static_cast(mParallelType) + << "-> mGTWRCore parallelType:" << static_cast(mGTWRCore->parallelType()) + << "parallelAbility:" << static_cast(mGTWRCore->parallelAbility()); + auto start_time = std::chrono::high_resolution_clock::now(); mBetas = mGTWRCore->fit(); + auto end_time = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast(end_time - start_time); + qDebug() << "fit() execution time (auto-select bandwidth):" << duration.count() << "ms, Threads:" << mOmpThreadNum; - gwm::BandwidthWeight* bw = mGTWRCore->spatialWeight().weight(); - if (bw && !checkCanceled()) + const auto &coreW = mGTWRCore->spatialWeight().weight(); + if (coreW && !checkCanceled()) { // 更新本地权重 - updateLocalSpatialWeight(bw); + gwm::BandwidthWeight& bw = mGTWRCore->spatialWeight().weight(); + updateLocalSpatialWeight(&bw); mCriterionList = mGTWRCore->bandwidthSelectionCriterionList(); QVector> qlist; @@ -95,9 +105,17 @@ void GwmGTWRAlgorithm::run() } else { - mGTWRCore->setParallelType(static_cast(mParallelType)); + mGTWRCore->setParallelType(mParallelType); + mGTWRCore->setOmpThreadNum(mOmpThreadNum); mGTWRCore->setTelegram(std::make_unique(this)); + qDebug() << "mParallelType:" << static_cast(mParallelType) + << "-> mGTWRCore parallelType:" << static_cast(mGTWRCore->parallelType()) + << "parallelAbility:" << static_cast(mGTWRCore->parallelAbility()); + auto start_time = std::chrono::high_resolution_clock::now(); mBetas = mGTWRCore->fit(); + auto end_time = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast(end_time - start_time); + qDebug() << "fit() execution time (no auto-select):" << duration.count() << "ms, Threads:" << mOmpThreadNum; } } @@ -743,36 +761,10 @@ void GwmGTWRAlgorithm::createResultLayer(GwmGTWRAlgorithm::CreateResultLayerData mResultLayer->commitChanges(); } -void GwmGTWRAlgorithm::setParallelType(const ParallelType &type) +void GwmGTWRAlgorithm::setParallelType(const gwm::ParallelType &type) { - if (type & parallelAbility()) - { - mParallelType = type; - if (mGTWRCore) - { - mGTWRCore->setParallelType(static_cast(type)); - } - setBandwidthSelectionCriterionType(mBandwidthSelectionCriterionType); - switch (type) { - case IParallelalbe::ParallelType::SerialOnly: - mRegressionFunction = &GwmGTWRAlgorithm::regressionSerial; - mRegressionHatmatrixFunction = &GwmGTWRAlgorithm::regressionHatmatrixSerial; - setBandwidthSelectionCriterionType(mBandwidthSelectionCriterionType); - break; -#ifdef ENABLE_OpenMP - case IParallelalbe::ParallelType::OpenMP: - mRegressionFunction = &GwmGTWRAlgorithm::regressionOmp; - mRegressionHatmatrixFunction = &GwmGTWRAlgorithm::regressionHatmatrixOmp; - setBandwidthSelectionCriterionType(mBandwidthSelectionCriterionType); - break; -#endif - default: - mRegressionFunction = &GwmGTWRAlgorithm::regressionSerial; - mRegressionHatmatrixFunction = &GwmGTWRAlgorithm::regressionHatmatrixSerial; - setBandwidthSelectionCriterionType(mBandwidthSelectionCriterionType); - break; - } - } + mParallelType = type; + mGTWRCore->setParallelType(type); } gwm::SpatialWeight GwmGTWRAlgorithm::convertSpatialWeight() @@ -808,10 +800,12 @@ gwm::SpatialWeight GwmGTWRAlgorithm::convertSpatialWeight() // 创建空间距离 (CRSDistance) GwmCRSDistance* gwmDist = mSTWeight.distance(); bool isGeographic = gwmDist ? gwmDist->geographic() : false; - gwm::CRSDistance* spatialDist = new gwm::CRSDistance(isGeographic); + std::unique_ptr spatialDist = + std::make_unique(isGeographic); // 创建时间距离 (OneDimDistance) - gwm::OneDimDistance* temporalDist = new gwm::OneDimDistance(); + std::unique_ptr temporalDist = + std::make_unique(); // 创建 CRSSTDistance,传入空间距离、时间距离和 lambda gwm::CRSSTDistance* dist = new gwm::CRSSTDistance( diff --git a/src/TaskThread/gwmgtwralgorithm.h b/src/TaskThread/gwmgtwralgorithm.h index baec794..0d7323b 100644 --- a/src/TaskThread/gwmgtwralgorithm.h +++ b/src/TaskThread/gwmgtwralgorithm.h @@ -6,11 +6,10 @@ #include "TaskThread/gwmspatialtemporalmonoscale.h" #include "TaskThread/iregressionanalysis.h" #include "TaskThread/gwmbandwidthsizeselector.h" -#include "TaskThread/iparallelable.h" #include -class GwmGTWRAlgorithm : public GwmSpatialTemporalMonoscaleAlgorithm, public IRegressionAnalysis, public IBandwidthSizeSelectable, public IOpenmpParallelable +class GwmGTWRAlgorithm : public GwmSpatialTemporalMonoscaleAlgorithm, public IRegressionAnalysis, public IBandwidthSizeSelectable, public gwm::IParallelizable, public gwm::IParallelOpenmpEnabled { Q_OBJECT @@ -91,13 +90,13 @@ class GwmGTWRAlgorithm : public GwmSpatialTemporalMonoscaleAlgorithm, public IRe public: double criterion(GwmBandwidthWeight *weight) override; - // IParallelalbe interface + // gwm::IParallelizable interface public: int parallelAbility() const override; - ParallelType parallelType() const override; - void setParallelType(const ParallelType &type) override; + gwm::ParallelType parallelType() const override; + void setParallelType(const gwm::ParallelType &type) override; - // IOpenmpParallelable interface + // gwm::IParallelOpenmpEnabled interface public: void setOmpThreadNum(const int threadNum) override; @@ -171,8 +170,8 @@ class GwmGTWRAlgorithm : public GwmSpatialTemporalMonoscaleAlgorithm, public IRe vec mRegressionLayerY; mat mRegressionLayerX; - ParallelType mParallelType = ParallelType::SerialOnly; - int mOmpThreadNum; + gwm::ParallelType mParallelType = gwm::ParallelType::SerialOnly; + int mOmpThreadNum = 8; bool mHasHatMatrix = true; @@ -229,18 +228,18 @@ inline GwmGTWRAlgorithm::BandwidthSelectionCriterionType GwmGTWRAlgorithm::bandw inline void GwmGTWRAlgorithm::setBandwidthSelectionCriterionType(const BandwidthSelectionCriterionType &bandwidthSelectionCriterionType) { - mBandwidthSelectionCriterionType = bandwidthSelectionCriterionType; - QMap, BandwidthSelectCriterionFunction> mapper = { - std::make_pair(qMakePair(BandwidthSelectionCriterionType::CV, IParallelalbe::ParallelType::SerialOnly), &GwmGTWRAlgorithm::bandwidthSizeCriterionCVSerial), - #ifdef ENABLE_OpenMP - std::make_pair(qMakePair(BandwidthSelectionCriterionType::CV, IParallelalbe::ParallelType::OpenMP), &GwmGTWRAlgorithm::bandwidthSizeCriterionCVOmp), - #endif - std::make_pair(qMakePair(BandwidthSelectionCriterionType::AIC, IParallelalbe::ParallelType::SerialOnly), &GwmGTWRAlgorithm::bandwidthSizeCriterionAICSerial), - #ifdef ENABLE_OpenMP - std::make_pair(qMakePair(BandwidthSelectionCriterionType::AIC, IParallelalbe::ParallelType::OpenMP), &GwmGTWRAlgorithm::bandwidthSizeCriterionAICOmp), - #endif - }; - mBandwidthSelectCriterionFunction = mapper[qMakePair(bandwidthSelectionCriterionType, mParallelType)]; + // mBandwidthSelectionCriterionType = bandwidthSelectionCriterionType; + // QMap, BandwidthSelectCriterionFunction> mapper = { + // std::make_pair(qMakePair(BandwidthSelectionCriterionType::CV, gwm::ParallelType::SerialOnly), &GwmGTWRAlgorithm::bandwidthSizeCriterionCVSerial), + // #ifdef ENABLE_OpenMP + // std::make_pair(qMakePair(BandwidthSelectionCriterionType::CV, gwm::ParallelType::OpenMP), &GwmGTWRAlgorithm::bandwidthSizeCriterionCVOmp), + // #endif + // std::make_pair(qMakePair(BandwidthSelectionCriterionType::AIC, gwm::ParallelType::SerialOnly), &GwmGTWRAlgorithm::bandwidthSizeCriterionAICSerial), + // #ifdef ENABLE_OpenMP + // std::make_pair(qMakePair(BandwidthSelectionCriterionType::AIC, gwm::ParallelType::OpenMP), &GwmGTWRAlgorithm::bandwidthSizeCriterionAICOmp), + // #endif + // }; + // mBandwidthSelectCriterionFunction = mapper[qMakePair(bandwidthSelectionCriterionType, mParallelType)]; } inline bool GwmGTWRAlgorithm::hasPredict() const @@ -295,7 +294,7 @@ inline void GwmGTWRAlgorithm::setHasHatMatrix(bool hasHatMatrix) inline double GwmGTWRAlgorithm::criterion(GwmBandwidthWeight *weight) { - return bandwidthSizeCriterionCVSerial(weight); + return (this->*mBandwidthSelectCriterionFunction)(weight); } inline mat GwmGTWRAlgorithm::betas() const @@ -311,14 +310,14 @@ inline BandwidthCriterionList GwmGTWRAlgorithm::bandwidthSelectorCriterions() co inline int GwmGTWRAlgorithm::parallelAbility() const { - return ParallelType::SerialOnly - #ifdef ENABLE_OpenMP - | ParallelType::OpenMP - #endif + return gwm::ParallelType::SerialOnly + #ifdef ENABLE_OpenMP + | gwm::ParallelType::OpenMP + #endif ; } -inline IParallelalbe::ParallelType GwmGTWRAlgorithm::parallelType() const +inline gwm::ParallelType GwmGTWRAlgorithm::parallelType() const { return mParallelType; } diff --git a/src/TaskThread/gwmgwcorrelationtaskthread.cpp b/src/TaskThread/gwmgwcorrelationtaskthread.cpp index 03b3c56..2378403 100644 --- a/src/TaskThread/gwmgwcorrelationtaskthread.cpp +++ b/src/TaskThread/gwmgwcorrelationtaskthread.cpp @@ -4,6 +4,8 @@ #include #endif +#include + using namespace gwm; using namespace std; @@ -168,17 +170,13 @@ void GwmGWCorrelationTaskThread::run() gwm::SpatialWeight sw(bw, dist); // 设置距离参数(坐标数据已经在 initPoints 中准备好了) - if (dist->type() == gwm::Distance::CRSDistance) { - auto *d = sw.distance(); - if (d) { - d->makeParameter({ mDataPoints, mDataPoints }); - } + if (dist->type() == gwm::Distance::DistanceType::CRSDistance) { + auto &d = sw.distance(); + d.makeParameter({ mDataPoints, mDataPoints }); } - else if (dist->type() == gwm::Distance::MinkwoskiDistance) { - auto *d2 = sw.distance(); - if (d2) { - d2->makeParameter({ mDataPoints, mDataPoints }); - } + else if (dist->type() == gwm::Distance::DistanceType::MinkwoskiDistance) { + auto &d2 = sw.distance(); + d2.makeParameter({ mDataPoints, mDataPoints }); } spatialWeights.push_back(sw); @@ -197,8 +195,6 @@ void GwmGWCorrelationTaskThread::run() mGWCorrCore->setBandwidthSelectionApproach(bandwidthSelTypes); mGWCorrCore->setParallelType(static_cast(mParallelType)); mGWCorrCore->setOmpThreadNum(mOmpThreadNum); - qDebug() << "core parallelType =" << mGWCorrCore->parallelType(); - qDebug() << "core parallelAbility =" << mGWCorrCore->parallelAbility(); // std::vector a = mGWCorrCore->spatialWeights(); // gwm::BandwidthWeight bwa = a[0].weight(); @@ -225,17 +221,24 @@ void GwmGWCorrelationTaskThread::run() emit message(tr("BandwidthInit size = %1").arg(bandwidthInitTypes.size())); emit message(tr("BandwidthSel size = %1").arg(bandwidthSelTypes.size())); + qDebug() << "mParallelType:" << static_cast(mParallelType) + << "-> mGWCorrCore parallelType:" << static_cast(mGWCorrCore->parallelType()) + << "parallelAbility:" << static_cast(mGWCorrCore->parallelAbility()); + auto __gwc_start = std::chrono::high_resolution_clock::now(); mGWCorrCore->run(); + auto __gwc_end = std::chrono::high_resolution_clock::now(); + auto __gwc_duration = std::chrono::duration_cast(__gwc_end - __gwc_start); + qDebug() << "GWCorrelation run() execution time:" << __gwc_duration.count() << "ms, Threads:" << mOmpThreadNum; // update property tab const std::vector& gwmSws = mGWCorrCore->spatialWeights(); for(uword i = 0 ; i(); - - if (gwmBw) + const auto& coreW = gwmSws[i].weight(); + if (coreW) { + gwm::BandwidthWeight& gwmBw = gwmSws[i].weight(); // 获取当前 GwmSpatialWeight 中的带宽权重 GwmBandwidthWeight* currentBw = mSpatialWeights[i].weight(); if (currentBw) @@ -243,11 +246,11 @@ void GwmGWCorrelationTaskThread::run() // 创建新的 GwmBandwidthWeight,使用更新后的带宽值 // 保持原有的 adaptive 和 kernel 设置 GwmBandwidthWeight::KernelFunctionType kernelType = - static_cast(gwmBw->kernel()); + static_cast(gwmBw.kernel()); GwmBandwidthWeight* newBw = new GwmBandwidthWeight( - gwmBw->bandwidth(), - gwmBw->adaptive(), + gwmBw.bandwidth(), + gwmBw.adaptive(), kernelType ); @@ -576,24 +579,8 @@ void GwmGWCorrelationTaskThread::createResultLayer(CreateResultLayerData data) //设置多线程字段 void GwmGWCorrelationTaskThread::setParallelType(const IParallelalbe::ParallelType &type) { - if (type & parallelAbility()) - { - mParallelType = type; - switch (type) { - case IParallelalbe::ParallelType::SerialOnly: -// mRegressionFunction = &GwmBasicGWRAlgorithm::regressionSerial; - mCalFunciton = &GwmGWCorrelationTaskThread::CalculateSerial; - break; -#ifdef ENABLE_OpenMP - case IParallelalbe::ParallelType::OpenMP: - mCalFunciton = &GwmGWCorrelationTaskThread::CalculateOmp; - break; -#endif - default: - mCalFunciton = &GwmGWCorrelationTaskThread::CalculateSerial; - break; - } - } + mParallelType = type; + mGWCorrCore->setParallelType(static_cast(type)); } //CV值计算 double GwmGWCorrelationTaskThread::bandwidthSizeCriterionVarCVSerial(GwmBandwidthWeight *bandwidthWeight) diff --git a/src/TaskThread/gwmgwpcataskthread.cpp b/src/TaskThread/gwmgwpcataskthread.cpp index 385a2e2..8427e77 100644 --- a/src/TaskThread/gwmgwpcataskthread.cpp +++ b/src/TaskThread/gwmgwpcataskthread.cpp @@ -34,7 +34,7 @@ void GwmGWPCATaskThread::run() { emit message(QString(tr("Setting data points ..."))); initPoints(); - + emit message(QString(tr("Setting X and Y."))); initXY(mX,mVariables); @@ -42,84 +42,98 @@ void GwmGWPCATaskThread::run() emit message(QString(tr("Zscore normalizaiton..."))); variableZscore(mX); } - } - + } + if(mIsAutoselectBandwidth && !checkCanceled()) { emit message(QString(tr("Automatically selecting bandwidth ..."))); emit tick(0, 0); - - if ((mSpatialWeight.distance()->type() == gwm::Distance::CRSDistance || - mSpatialWeight.distance()->type() == gwm::Distance::MinkwoskiDistance) && !checkCanceled()) + + if ((mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::CRSDistance || + mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::MinkwoskiDistance) && !checkCanceled()) { - gwm::CRSDistance* d = static_cast(mSpatialWeight.distance()); - if(d) + // gwm::CRSDistance* d = static_cast(mSpatialWeight.distance()); + // if(d) + // { + // d->makeParameter({ mDataPoints, mDataPoints }); + // } + if (mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::CRSDistance) { - d->makeParameter({ mDataPoints, mDataPoints }); + auto &d = mSpatialWeight.distance(); + d.makeParameter({ mDataPoints, mDataPoints }); + } + else if (mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::MinkwoskiDistance) + { + auto &d2 = mSpatialWeight.distance(); + d2.makeParameter({ mDataPoints, mDataPoints }); } } - - gwm::BandwidthWeight* bandwidthWeight0 = mSpatialWeight.weight(); - if(!bandwidthWeight0) + + const auto &bwHolder = mSpatialWeight.weight(); + if(!bwHolder) { + qDebug() << "[GWPCA] ERROR: Cannot get bandwidth weight!"; emit error(tr("Cannot get bandwidth weight for bandwidth selection.")); return; } - + + gwm::BandwidthWeight& bandwidthWeight0 = mSpatialWeight.weight(); + double tmpMaxD = mSpatialWeight.distance()->maxDistance(); - double lower = bandwidthWeight0->adaptive() ? 2 : tmpMaxD / 5000; - double upper = bandwidthWeight0->adaptive() ? mDataPoints.n_rows : tmpMaxD; - - if(bandwidthWeight0->bandwidth() <= 0 || - (bandwidthWeight0->adaptive() && bandwidthWeight0->bandwidth() < lower) || - (!bandwidthWeight0->adaptive() && bandwidthWeight0->bandwidth() < lower)) + double lower = bandwidthWeight0.adaptive() ? 2 : tmpMaxD / 5000; + double upper = bandwidthWeight0.adaptive() ? mDataPoints.n_rows : tmpMaxD; + + if(bandwidthWeight0.bandwidth() <= 0 || + (bandwidthWeight0.adaptive() && bandwidthWeight0.bandwidth() < lower) || + (!bandwidthWeight0.adaptive() && bandwidthWeight0.bandwidth() < lower)) { - double initialBandwidth = bandwidthWeight0->adaptive() ? - std::max(2.0, std::min(20.0, (double)mDataPoints.n_rows * 0.1)) : + double initialBandwidth = bandwidthWeight0.adaptive() ? + std::max(2.0, std::min(20.0, (double)mDataPoints.n_rows * 0.1)) : std::max(lower, tmpMaxD * 0.1); - bandwidthWeight0->setBandwidth(initialBandwidth); + bandwidthWeight0.setBandwidth(initialBandwidth); } - - mSelector.setBandwidth(bandwidthWeight0); - mSelector.setLower(lower); - mSelector.setUpper(upper); - + try { - gwm::BandwidthWeight* bandwidthWeight = mSelector.optimize(this); - if(bandwidthWeight && !checkCanceled()) + gwm::BandwidthSelector selector(bandwidthWeight0, lower, upper); + gwm::Status optStatus = selector.optimize(this); + if (optStatus == gwm::Status::Terminated || checkCanceled()) { - mSpatialWeight.setWeight(bandwidthWeight); - mSelector.setBandwidth(bandwidthWeight); - - gwm::BandwidthWeight* verifyBw = mSpatialWeight.weight(); - if(verifyBw && verifyBw->bandwidth() == 0) + return; + } + const gwm::BandwidthWeight& rw = selector.result(); + // auto* applied = new GwmBandwidthWeight( + // rw.bandwidth(), + // rw.adaptive(), + // static_cast(rw.kernel())); + mSpatialWeight.setWeight(rw); + mBandwidthCriterionCache = selector.bandwidthCriterion(); + + const auto &verifyHolder = mSpatialWeight.weight(); + if (verifyHolder) + { + gwm::BandwidthWeight &verifyBw = mSpatialWeight.weight(); + if (verifyBw.bandwidth() == 0) { qDebug() << "[GWPCA] ERROR: Bandwidth is 0 after setWeight! This may cause display issues."; } } - else if(!bandwidthWeight) - { - qDebug() << "[GWPCA] WARNING: Bandwidth optimization returned NULL"; - emit error(tr("Bandwidth optimization failed: no optimal bandwidth found.")); - return; - } } - catch(const std::exception& e) + catch (const std::exception& e) { qDebug() << "[GWPCA] EXCEPTION during bandwidth optimization:" << e.what(); emit error(QString(tr("Bandwidth optimization error: %1")).arg(e.what())); return; } - catch(...) + catch (...) { qDebug() << "[GWPCA] UNKNOWN EXCEPTION during bandwidth optimization"; emit error(tr("Unknown error occurred during bandwidth optimization.")); return; } } - + if(!checkCanceled()) { emit message(QString(tr("Principle components analyzing ..."))); @@ -138,12 +152,12 @@ void GwmGWPCATaskThread::run() } mLocalPV = robustSolveSerial(mX, mLoadings, mSDev); - + if(checkCanceled()) { return; } - + mVariance = mSDev % mSDev; // Robust 分支在 robustSolveSerial() 内已按需要同步填充 mScores。 @@ -156,22 +170,22 @@ void GwmGWPCATaskThread::run() emit error(tr("GWPCA algorithm object is not initialized.")); return; } - + mAlgorithm->setCoords(mDataPoints); mAlgorithm->setVariables(mX); mAlgorithm->setSpatialWeight(mSpatialWeight); mAlgorithm->setKeepComponents(mK); - + if(!mAlgorithm->isValid()) { qDebug() << "[GWPCA] ERROR: Algorithm configuration is invalid!"; emit error(tr("GWPCA algorithm configuration is invalid.")); return; } - + mAlgorithm->setTelegram(std::make_unique(this)); mAlgorithm->run(); - + auto status = mAlgorithm->status(); if(status != gwm::Status::Success) { @@ -179,7 +193,7 @@ void GwmGWPCATaskThread::run() emit error(tr("GWPCA algorithm execution failed.")); return; } - + mLocalPV = mAlgorithm->localPV(); mLoadings = mAlgorithm->loadings(); mSDev = mAlgorithm->sdev(); @@ -247,7 +261,7 @@ void GwmGWPCATaskThread::run() { win_var_PC1.append(mVariables.at(iWinVar(i)).name); } - + if(!checkCanceled()) { CreateResultLayerData resultLayerData = { @@ -260,7 +274,7 @@ void GwmGWPCATaskThread::run() } }; createResultLayer(resultLayerData,win_var_PC1); - + if(getPlot()){ CreatePlotLayerData plotLayerData = {}; vec vecLoadings(mDataPoints.n_rows * mVariables.size()); @@ -287,12 +301,14 @@ void GwmGWPCATaskThread::run() bool GwmGWPCATaskThread::isValid() { - gwm::BandwidthWeight* bandwidth = static_cast(mSpatialWeight.weight()); - if(bandwidth){ + const auto &wh = mSpatialWeight.weight(); + if(wh){ + gwm::BandwidthWeight &bandwidth = mSpatialWeight.weight(); + if(!mIsAutoselectBandwidth) { - if(bandwidth->adaptive()){ - if(bandwidth->bandwidth() <= mVariables.size()){ + if(bandwidth.adaptive()){ + if(bandwidth.bandwidth() <= mVariables.size()){ return false; } } @@ -316,10 +332,10 @@ void GwmGWPCATaskThread::initPoints() qDebug() << "[GWPCA::initPoints] ERROR: Data layer is NULL!"; return; } - + int nDp = mDataLayer->featureCount(); mDataPoints = mat(nDp, 2, fill::zeros); - + QgsFeatureIterator iterator = mDataLayer->getFeatures(); QgsFeature f; for (int i = 0; iterator.nextFeature(f); i++) @@ -334,9 +350,9 @@ void GwmGWPCATaskThread::initPoints() void GwmGWPCATaskThread::initXY(mat &x, const QList &indepVars) { int nDp = mDataLayer->featureCount(), nVar = indepVars.size(); - + x = mat(nDp, nVar, fill::zeros); - + QgsFeatureIterator iterator = mDataLayer->getFeatures(); QgsFeature f; bool ok = false; @@ -346,11 +362,11 @@ void GwmGWPCATaskThread::initXY(mat &x, const QList &indepVars) for (int k = 0; k < indepVars.size(); k++) { double vX = f.attribute(indepVars[k].name).toDouble(&ok); - if (ok) + if (ok) { x(i, k) = vX; } - else + else { errorCount++; if(errorCount <= 5) @@ -380,19 +396,19 @@ void GwmGWPCATaskThread::calculateScores() qDebug() << "[GWPCA] calculateScores() called: computing scores locally with" << (Robust() ? "robust" : "non-robust") << "PCA."; mScores = cube(nDp, mK, nDp, fill::zeros); - + for(uword i = 0; i < nDp && !checkCanceled(); i++) { vec wt = mSpatialWeight.weightVector(i); uvec positive = find(wt > 0); vec newWt = wt.elem(positive); mat newX = mX.rows(positive); - + if(newWt.n_rows <= 5) { break; } - + mat V; vec d; if(!Robust()){ @@ -400,7 +416,7 @@ void GwmGWPCATaskThread::calculateScores() }else{ rwpca(newX, newWt, V, d); } - + mat scorei(nDp, mK, fill::zeros); for(int j = 0; j < mK && !checkCanceled(); j++) { @@ -449,7 +465,7 @@ void GwmGWPCATaskThread::rwpca(const mat &x, const vec &wt, mat &V, vec &S) mat mids = x; mids = mids.each_row() - x.row((abs(wt - 0.5)).index_min()); - + mat score; vec tsquared; princomp(V, score, S, tsquared, mids.each_col() % wt); @@ -469,7 +485,7 @@ mat GwmGWPCATaskThread::robustSolveSerial(const mat& x, cube& loadings, mat& sde { mScores = cube(nDp, mK, nDp, fill::zeros); } - + for(int i=0;idistance(i); @@ -520,30 +536,30 @@ mat GwmGWPCATaskThread::robustSolveSerial(const mat& x, cube& loadings, mat& sde return pv; } -gwm::Status GwmGWPCATaskThread::getCriterion(gwm::BandwidthWeight* weight, double& criterion) +gwm::Status GwmGWPCATaskThread::getCriterion(const std::unique_ptr& weight, double& criterion) { - if(checkCanceled()) + if (!weight || checkCanceled()) { criterion = DBL_MAX; - return gwm::Status::Terminated; + return checkCanceled() ? gwm::Status::Terminated : gwm::Status::Success; } - - // 将内核库的BandwidthWeight转换为本地的GwmBandwidthWeight - GwmBandwidthWeight::KernelFunctionType kernelType = static_cast(weight->kernel()); + + GwmBandwidthWeight::KernelFunctionType kernelType = + static_cast(weight->kernel()); GwmBandwidthWeight localWeight(weight->bandwidth(), weight->adaptive(), kernelType); - + try { criterion = (this->*mBandwidthSelectCriterionFunction)(&localWeight); return gwm::Status::Success; } - catch(const std::exception& e) + catch (const std::exception& e) { qDebug() << "[GWPCA::getCriterion] EXCEPTION:" << e.what(); criterion = DBL_MAX; return gwm::Status::Success; } - catch(...) + catch (...) { qDebug() << "[GWPCA::getCriterion] UNKNOWN EXCEPTION"; criterion = DBL_MAX; @@ -782,14 +798,11 @@ double GwmGWPCATaskThread::bandwidthSizeCriterionCVSerial(GwmBandwidthWeight *we int m = mX.n_cols; double score = 0; - if (mSpatialWeight.distance()->type() == gwm::Distance::CRSDistance || - mSpatialWeight.distance()->type() == gwm::Distance::MinkwoskiDistance) + if (mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::CRSDistance || + mSpatialWeight.distance()->type() == gwm::Distance::DistanceType::MinkwoskiDistance) { - gwm::CRSDistance* d = static_cast(mSpatialWeight.distance()); - if(d) - { - d->makeParameter({ mDataPoints, mDataPoints }); - } + gwm::CRSDistance& d = mSpatialWeight.distance(); // static_cast(mSpatialWeight.distance()); + d.makeParameter({ mDataPoints, mDataPoints }); } for (int i = 0; i < n && !checkCanceled(); i++) @@ -801,7 +814,7 @@ double GwmGWPCATaskThread::bandwidthSizeCriterionCVSerial(GwmBandwidthWeight *we score = DBL_MAX; break; } - + vec wt = weight->weight(distvi); wt(i) = 0; @@ -812,7 +825,7 @@ double GwmGWPCATaskThread::bandwidthSizeCriterionCVSerial(GwmBandwidthWeight *we score = DBL_MAX; break; } - + vec newWt = wt.elem(positive); mat newX = mX.rows(positive); //判断length(newWt) @@ -822,7 +835,7 @@ double GwmGWPCATaskThread::bandwidthSizeCriterionCVSerial(GwmBandwidthWeight *we score = DBL_MAX; break; } - + mat V; vec S; try @@ -844,7 +857,7 @@ double GwmGWPCATaskThread::bandwidthSizeCriterionCVSerial(GwmBandwidthWeight *we score = DBL_MAX; break; } - + mBandwidthCounter++; if (mBandwidthCounter < 10) emit tick(mBandwidthCounter * 10 + i * 5 / n, 100); @@ -859,8 +872,7 @@ double GwmGWPCATaskThread::bandwidthSizeCriterionCVOmp(GwmBandwidthWeight *weigh double score = 0; bool flag = true; vec score_all(mOmpThreadNum, fill::zeros); - int current = 0; - const int selectorStep = static_cast(mSelector.bandwidthCriterion().size()); + // int current = 0; #pragma omp parallel for num_threads(mOmpThreadNum) for (int i = 0; i < n; i++) { @@ -889,9 +901,9 @@ double GwmGWPCATaskThread::bandwidthSizeCriterionCVOmp(GwmBandwidthWeight *weigh } // if(mSelector.counter<10) // emit tick(mSelector.counter * 10 + current * 10 / n, 100); - if (selectorStep < 10) - emit tick(selectorStep * 10 + current * 10 / n, 100); - current++; + // current++; + if (i % std::max(1, n / 10) == 0) + emit tick(i * 100 / n, 100); } } score = sum(score_all); diff --git a/src/TaskThread/gwmgwpcataskthread.h b/src/TaskThread/gwmgwpcataskthread.h index 3d656d4..1dea73a 100644 --- a/src/TaskThread/gwmgwpcataskthread.h +++ b/src/TaskThread/gwmgwpcataskthread.h @@ -1,4 +1,4 @@ -#ifndef GWMGWPCATASKTHREAD_H +#ifndef GWMGWPCATASKTHREAD_H #define GWMGWPCATASKTHREAD_H #include @@ -8,6 +8,7 @@ #include "TaskThread/gwmbandwidthsizeselector.h" #include +// #include // in case that std::unique_ptr cannot be found class GwmGWPCATaskThread : public GwmSpatialMonoscaleAlgorithm, public IBandwidthSizeSelectable, public IGwmMultivariableAnalysis, public IOpenmpParallelable, public gwm::IBandwidthSelectable { @@ -48,7 +49,8 @@ class GwmGWPCATaskThread : public GwmSpatialMonoscaleAlgorithm, public IBandwidt BandwidthCriterionList bandwidthSelectorCriterions() const { - return mSelector.bandwidthCriterion(); + // return mSelector.bandwidthCriterion(); + return mBandwidthCriterionCache; } double k() const; @@ -130,7 +132,7 @@ class GwmGWPCATaskThread : public GwmSpatialMonoscaleAlgorithm, public IBandwidt } public: // gwm::IBandwidthSelectable interface - gwm::Status getCriterion(gwm::BandwidthWeight* weight, double& criterion) override; + gwm::Status getCriterion(const std::unique_ptr& weight, double& criterion) override; private: QList mVariables; @@ -141,7 +143,8 @@ class GwmGWPCATaskThread : public GwmSpatialMonoscaleAlgorithm, public IBandwidt mat mX; vec mLatestWt; - gwm::BandwidthSelector mSelector; + // gwm::BandwidthSelector mSelector; + BandwidthCriterionList mBandwidthCriterionCache; BandwidthSelectionCriterionType mBandwidthSelectionCriterionType = BandwidthSelectionCriterionType::CV; BandwidthSelectCriterionFunction mBandwidthSelectCriterionFunction = &GwmGWPCATaskThread::bandwidthSizeCriterionCVSerial; bool mIsAutoselectBandwidth = false; diff --git a/src/TaskThread/gwmlocalcollinearitygwralgorithm.cpp b/src/TaskThread/gwmlocalcollinearitygwralgorithm.cpp index 7d83f18..3790812 100644 --- a/src/TaskThread/gwmlocalcollinearitygwralgorithm.cpp +++ b/src/TaskThread/gwmlocalcollinearitygwralgorithm.cpp @@ -6,6 +6,8 @@ #include #endif +#include + int GwmLocalCollinearityGWRAlgorithm::treeChildCount = 0; using namespace arma; @@ -43,16 +45,6 @@ void GwmLocalCollinearityGWRAlgorithm::setCanceled(bool canceled) return GwmTaskThread::setCanceled(canceled); } -void GwmLocalCollinearityGWRAlgorithm::setGPUId(const int gpuId) -{ - mGpuId = gpuId; -} - -void GwmLocalCollinearityGWRAlgorithm::setGroupSize(const std::size_t size) -{ - mGroupSize = static_cast(size); -} - void GwmLocalCollinearityGWRAlgorithm::run() { if(!checkCanceled()) @@ -81,26 +73,24 @@ void GwmLocalCollinearityGWRAlgorithm::run() vec hatrow(mDataPoints.n_rows,fill::zeros); //yhat赋值 emit message("Regressoin..."); - // mBetas = regression(mX, mY); mLCGWRCore->setTelegram(std::make_unique(this)); - mLCGWRCore->setParallelType(mParallelType); + emit message("Regression ..."); + mLCGWRCore->setParallelType(static_cast(mParallelType)); mLCGWRCore->setOmpThreadNum(mOmpThreadNum); - qDebug() << "core parallelType =" << mLCGWRCore->parallelType(); - qDebug() << "core parallelAbility =" << mLCGWRCore->parallelAbility(); - - QElapsedTimer timer; - timer.start(); - + mLCGWRCore->setTelegram(std::make_unique(this)); + qDebug() << "mParallelType:" << static_cast(mParallelType) + << "-> mLCGWRCore parallelType:" << static_cast(mLCGWRCore->parallelType()) + << "parallelAbility:" << static_cast(mLCGWRCore->parallelAbility()); + auto __lcr_start = std::chrono::high_resolution_clock::now(); mBetas = mLCGWRCore->fit(); + auto __lcr_end = std::chrono::high_resolution_clock::now(); + auto __lcr_duration = std::chrono::duration_cast(__lcr_end - __lcr_start); + qDebug() << "fit() execution time:" << __lcr_duration.count() << "ms, Threads:" << mOmpThreadNum; + qDebug() << "mBetas:"; mBetas.print(); - qint64 elapsed = timer.elapsed(); - qDebug() << "fit() time =" << elapsed << "ms"; - - // std::cout << "mBetas = \n" << mBetas << std::endl; - - gwm::BandwidthWeight* bw = mLCGWRCore->spatialWeight().weight(); + gwm::BandwidthWeight& bw = mLCGWRCore->spatialWeight().weight(); mSpatialWeight.setWeight(bw); criterionList = mLCGWRCore->bandwidthSelectionCriterionList(); @@ -139,18 +129,18 @@ bool GwmLocalCollinearityGWRAlgorithm::isAutoselectBandwidth() const return mIsAutoselectBandwidth; } -void GwmLocalCollinearityGWRAlgorithm::setBandwidthSelectionCriterionType(const gwm::GWRBasic::BandwidthSelectionCriterionType &bandwidthSelectionCriterionType) +void GwmLocalCollinearityGWRAlgorithm::setBandwidthSelectionCriterionType(const GwmLocalCollinearityGWRAlgorithm::BandwidthSelectionCriterionType &bandwidthSelectionCriterionType) { mBandwidthSelectionCriterionType = bandwidthSelectionCriterionType; - QMap, BandwidthSelectCriterionFunction> mapper = { - std::make_pair(qMakePair(gwm::GWRBasic::CV, gwm::ParallelType::SerialOnly), &GwmLocalCollinearityGWRAlgorithm::bandwidthSizeCriterionCVSerial), + QMap, BandwidthSelectCriterionFunction> mapper = { + std::make_pair(qMakePair(BandwidthSelectionCriterionType::CV, IParallelalbe::ParallelType::SerialOnly), &GwmLocalCollinearityGWRAlgorithm::bandwidthSizeCriterionCVSerial), #ifdef ENABLE_OpenMP - std::make_pair(qMakePair(gwm::GWRBasic::CV, gwm::ParallelType::OpenMP), &GwmLocalCollinearityGWRAlgorithm::bandwidthSizeCriterionCVOmp), + std::make_pair(qMakePair(BandwidthSelectionCriterionType::CV, IParallelalbe::ParallelType::OpenMP), &GwmLocalCollinearityGWRAlgorithm::bandwidthSizeCriterionCVOmp), #endif - //std::make_pair(qMakePair(BandwidthSelectionCriterionType::CV, gwm::ParallelType::CUDA), &GwmLcrGWRTaskThread::bandwidthSizeCriterionCVCuda), - //std::make_pair(qMakePair(BandwidthSelectionCriterionType::AIC, gwm::ParallelType::SerialOnly), &GwmLcrGWRTaskThread::bandwidthSizeCriterionAICSerial), - //std::make_pair(qMakePair(BandwidthSelectionCriterionType::AIC, gwm::ParallelType::OpenMP), &GwmLcrGWRTaskThread::bandwidthSizeCriterionAICOmp), - //std::make_pair(qMakePair(BandwidthSelectionCriterionType::AIC, gwm::ParallelType::CUDA), &GwmLcrGWRTaskThread::bandwidthSizeCriterionAICCuda) + //std::make_pair(qMakePair(BandwidthSelectionCriterionType::CV, IParallelalbe::ParallelType::CUDA), &GwmLcrGWRTaskThread::bandwidthSizeCriterionCVCuda), + //std::make_pair(qMakePair(BandwidthSelectionCriterionType::AIC, IParallelalbe::ParallelType::SerialOnly), &GwmLcrGWRTaskThread::bandwidthSizeCriterionAICSerial), + //std::make_pair(qMakePair(BandwidthSelectionCriterionType::AIC, IParallelalbe::ParallelType::OpenMP), &GwmLcrGWRTaskThread::bandwidthSizeCriterionAICOmp), + //std::make_pair(qMakePair(BandwidthSelectionCriterionType::AIC, IParallelalbe::ParallelType::CUDA), &GwmLcrGWRTaskThread::bandwidthSizeCriterionAICCuda) }; mBandwidthSelectCriterionFunction = mapper[qMakePair(bandwidthSelectionCriterionType, mParallelType)]; } @@ -347,8 +337,7 @@ double GwmLocalCollinearityGWRAlgorithm::bandwidthSizeCriterionCVOmp(GwmBandwidt //取mX不含第一列的部分 mat mXnot1 = mX.cols(1, mX.n_cols - 1); //主循环 - int current = 0; - const int selectorStep = static_cast(selector.bandwidthCriterion().size()); + // int current = 0; #pragma omp parallel for num_threads(mOmpThreadNum) for (int i = 0; i < n; i++) { @@ -384,9 +373,9 @@ double GwmLocalCollinearityGWRAlgorithm::bandwidthSizeCriterionCVOmp(GwmBandwidt betas.row(i) = trans( ridgelm(wgt,locallambda(i)) ); // if(selector.counter<10) // emit tick(selector.counter*10 + current * 10 / n, 100); - if (selectorStep < 10) - emit tick(selectorStep * 10 + current * 10 / n, 100); - current++; + if (i % std::max(1, n / 10) == 0) + emit tick(i * 100 / n, 100); + // current++; } } //yhat赋值 @@ -523,12 +512,28 @@ mat GwmLocalCollinearityGWRAlgorithm::regressionOmp(const mat &x, const vec &y) return betas; } #endif -void GwmLocalCollinearityGWRAlgorithm::setParallelType(const gwm::ParallelType &type) +void GwmLocalCollinearityGWRAlgorithm::setParallelType(const IParallelalbe::ParallelType &type) { - if (mLCGWRCore && (type & mLCGWRCore->parallelAbility())) + if(type & parallelAbility()) { mParallelType = type; - mLCGWRCore->setParallelType(type); + switch(type) + { + case IParallelalbe::ParallelType::SerialOnly: + setBandwidthSelectionCriterionType(mBandwidthSelectionCriterionType); + mRegressionFunction = &GwmLocalCollinearityGWRAlgorithm::regressionSerial; + break; +#ifdef ENABLE_OpenMP + case IParallelalbe::ParallelType::OpenMP: + setBandwidthSelectionCriterionType(mBandwidthSelectionCriterionType); + mRegressionFunction = &GwmLocalCollinearityGWRAlgorithm::regressionOmp; + break; +#endif + default: + setBandwidthSelectionCriterionType(mBandwidthSelectionCriterionType); + mRegressionFunction = &GwmLocalCollinearityGWRAlgorithm::regressionSerial; + break; + } } } @@ -561,12 +566,12 @@ bool GwmLocalCollinearityGWRAlgorithm::isValid() { if (GwmGeographicalWeightedRegressionAlgorithm::isValid()) { - gwm::BandwidthWeight* bandwidth = static_cast(mSpatialWeight.weight()); + gwm::BandwidthWeight& bandwidth = mSpatialWeight.weight();//static_cast(mSpatialWeight.weight()); if(!mIsAutoselectBandwidth) { - if(bandwidth->adaptive()){ - if (bandwidth->bandwidth() <= mIndepVars.size()) return false; + if(bandwidth.adaptive()){ + if (bandwidth.bandwidth() <= mIndepVars.size()) return false; }else{ } diff --git a/src/TaskThread/gwmlocalcollinearitygwralgorithm.h b/src/TaskThread/gwmlocalcollinearitygwralgorithm.h index cc25739..04e6534 100644 --- a/src/TaskThread/gwmlocalcollinearitygwralgorithm.h +++ b/src/TaskThread/gwmlocalcollinearitygwralgorithm.h @@ -11,7 +11,7 @@ using namespace arma; -class GwmLocalCollinearityGWRAlgorithm:public GwmGeographicalWeightedRegressionAlgorithm, public IBandwidthSizeSelectable, public gwm::IParallelizable, public gwm::IParallelOpenmpEnabled, public gwm::IParallelCudaEnabled +class GwmLocalCollinearityGWRAlgorithm:public GwmGeographicalWeightedRegressionAlgorithm, public IBandwidthSizeSelectable,public IOpenmpParallelable { public: @@ -71,8 +71,8 @@ class GwmLocalCollinearityGWRAlgorithm:public GwmGeographicalWeightedRegressionA return criterionList; } - gwm::GWRBasic::BandwidthSelectionCriterionType bandwidthSelectionCriterionType() const; - void setBandwidthSelectionCriterionType(const gwm::GWRBasic::BandwidthSelectionCriterionType &bandwidthSelectionCriterionType); + BandwidthSelectionCriterionType bandwidthSelectionCriterionType() const; + void setBandwidthSelectionCriterionType(const BandwidthSelectionCriterionType &bandwidthSelectionCriterionType); public: bool isValid() override; @@ -92,18 +92,14 @@ class GwmLocalCollinearityGWRAlgorithm:public GwmGeographicalWeightedRegressionA void createResultLayer(CreateResultLayerData data); public: int parallelAbility() const override; - gwm::ParallelType parallelType() const override; + ParallelType parallelType() const override; - void setParallelType(const gwm::ParallelType &type) override; + void setParallelType(const ParallelType &type) override; // IOpenmpParallelable interface public: void setOmpThreadNum(const int threadNum) override; - // IParallelCudaEnabled interface - void setGPUId(const int gpuId) override; - void setGroupSize(const std::size_t size) override; - void setCanceled(bool canceled) override; private: double mLambda; @@ -112,7 +108,7 @@ class GwmLocalCollinearityGWRAlgorithm:public GwmGeographicalWeightedRegressionA double mCnThresh; - gwm::BandwidthSelector selector; + //gwm::BandwidthSelector selector; bool mHasHatmatix = false; @@ -131,7 +127,7 @@ class GwmLocalCollinearityGWRAlgorithm:public GwmGeographicalWeightedRegressionA #ifdef ENABLE_OpenMP double bandwidthSizeCriterionCVOmp(GwmBandwidthWeight* weight); #endif - gwm::GWRBasic::BandwidthSelectionCriterionType mBandwidthSelectionCriterionType = gwm::GWRBasic::BandwidthSelectionCriterionType::CV; + BandwidthSelectionCriterionType mBandwidthSelectionCriterionType = BandwidthSelectionCriterionType::CV; BandwidthSelectCriterionFunction mBandwidthSelectCriterionFunction = &GwmLocalCollinearityGWRAlgorithm::bandwidthSizeCriterionCVSerial; mat regressionSerial(const mat& x, const vec& y); @@ -140,7 +136,7 @@ class GwmLocalCollinearityGWRAlgorithm:public GwmGeographicalWeightedRegressionA #endif Regression mRegressionFunction = &GwmLocalCollinearityGWRAlgorithm::regressionSerial; - gwm::ParallelType mParallelType = gwm::ParallelType::SerialOnly; + IParallelalbe::ParallelType mParallelType = IParallelalbe::ParallelType::SerialOnly; int mOmpThreadNum = 8; int mGpuId = 0; int mGroupSize = 64; @@ -150,10 +146,10 @@ class GwmLocalCollinearityGWRAlgorithm:public GwmGeographicalWeightedRegressionA inline int GwmLocalCollinearityGWRAlgorithm::parallelAbility() const { - return mLCGWRCore ? mLCGWRCore->parallelAbility() : (gwm::SerialOnly | gwm::OpenMP); + return IParallelalbe::SerialOnly | IParallelalbe::OpenMP; } -inline gwm::ParallelType GwmLocalCollinearityGWRAlgorithm::parallelType() const +inline IParallelalbe::ParallelType GwmLocalCollinearityGWRAlgorithm::parallelType() const { return mParallelType; } @@ -161,10 +157,6 @@ inline gwm::ParallelType GwmLocalCollinearityGWRAlgorithm::parallelType() const inline void GwmLocalCollinearityGWRAlgorithm::setOmpThreadNum(const int threadNum) { mOmpThreadNum = threadNum; - if (mLCGWRCore) - { - mLCGWRCore->setOmpThreadNum(threadNum); - } } #endif // GWMLCRGWRTASKTHREAD_H diff --git a/src/TaskThread/gwmmultiscalegwralgorithm.cpp b/src/TaskThread/gwmmultiscalegwralgorithm.cpp index 28fd875..d1047f3 100644 --- a/src/TaskThread/gwmmultiscalegwralgorithm.cpp +++ b/src/TaskThread/gwmmultiscalegwralgorithm.cpp @@ -3,6 +3,7 @@ #include #endif #include +#include #include "GWmodel/GWmodel.h" #include @@ -174,17 +175,13 @@ void GwmMultiscaleGWRAlgorithm::run() gwm::SpatialWeight sw(bw, dist); // 设置距离参数(坐标数据已经在 initPoints 中准备好了) - if (dist->type() == gwm::Distance::CRSDistance) { - auto *d = sw.distance(); - if (d) { - d->makeParameter({ mRegressionPoints, mDataPoints }); - } + if (dist->type() == gwm::Distance::DistanceType::CRSDistance) { + auto &d = sw.distance(); + d.makeParameter({ mRegressionPoints, mDataPoints }); } - else if (dist->type() == gwm::Distance::MinkwoskiDistance) { - auto *d2 = sw.distance(); - if (d2) { - d2->makeParameter({ mRegressionPoints, mDataPoints }); - } + else if (dist->type() == gwm::Distance::DistanceType::MinkwoskiDistance) { + auto &d2 = sw.distance(); + d2.makeParameter({ mRegressionPoints, mDataPoints }); } spatialWeights.push_back(sw); @@ -227,13 +224,11 @@ void GwmMultiscaleGWRAlgorithm::run() mMGWRCore->setAdaptiveLower(mAdaptiveLower); // 7. 设置并行类型 - gwm::ParallelType parallelType = gwm::ParallelType::SerialOnly; - if (mParallelType == IParallelalbe::OpenMP) - { - parallelType = gwm::ParallelType::OpenMP; - mMGWRCore->setOmpThreadNum(mOmpThreadNum); - } - mMGWRCore->setParallelType(parallelType); + mMGWRCore->setParallelType(mParallelType); + mMGWRCore->setOmpThreadNum(mOmpThreadNum); + qDebug() << "mParallelType:" << static_cast(mParallelType) + << "-> mMGWRCore parallelType:" << static_cast(mMGWRCore->parallelType()) + << "parallelAbility:" << static_cast(mMGWRCore->parallelAbility()); // 8. 设置初始空间权重(不需要) // 9. 设置消息传递(如果需要) @@ -246,7 +241,11 @@ void GwmMultiscaleGWRAlgorithm::run() emit message(tr("Running MGWR using core library...")); try { + auto start_time = std::chrono::high_resolution_clock::now(); mBetas = mMGWRCore->fit(); + auto end_time = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast(end_time - start_time); + qDebug() << "fit() execution time:" << duration.count() << "ms, Threads:" << mOmpThreadNum; std::vector ws = mMGWRCore->spatialWeights(); // 确保数量匹配 @@ -254,13 +253,14 @@ void GwmMultiscaleGWRAlgorithm::run() { for (size_t i = 0; i < ws.size(); i++) { - gwm::BandwidthWeight* gwmBw = ws[i].weight(); - if (gwmBw) + const auto& coreW = ws[i].weight(); + if (coreW) { + gwm::BandwidthWeight& gwmBw = ws[i].weight(); // 从库的带宽权重中提取参数 - double bandwidth = gwmBw->bandwidth(); - bool adaptive = gwmBw->adaptive(); - gwm::BandwidthWeight::KernelFunctionType gwmKernel = gwmBw->kernel(); + double bandwidth = gwmBw.bandwidth(); + bool adaptive = gwmBw.adaptive(); + gwm::BandwidthWeight::KernelFunctionType gwmKernel = gwmBw.kernel(); // 转换为应用层的类型 GwmBandwidthWeight::KernelFunctionType kernel = convertKernelTypeBack(gwmKernel); @@ -1290,20 +1290,20 @@ double GwmMultiscaleGWRAlgorithm::mBandwidthSizeCriterionVarAICOmp(GwmBandwidthW #endif GwmMultiscaleGWRAlgorithm::BandwidthSizeCriterionFunction GwmMultiscaleGWRAlgorithm::bandwidthSizeCriterionAll(GwmMultiscaleGWRAlgorithm::BandwidthSelectionCriterionType type) { - QMap > mapper = { - std::make_pair >(BandwidthSelectionCriterionType::CV, { - std::make_pair(IParallelalbe::ParallelType::SerialOnly, &GwmMultiscaleGWRAlgorithm::mBandwidthSizeCriterionAllCVSerial), + QMap > mapper = { + std::make_pair >(BandwidthSelectionCriterionType::CV, { + std::make_pair(gwm::ParallelType::SerialOnly, &GwmMultiscaleGWRAlgorithm::mBandwidthSizeCriterionAllCVSerial), #ifdef ENABLE_OpenMP std::make_pair(IParallelalbe::ParallelType::OpenMP, &GwmMultiscaleGWRAlgorithm::mBandwidthSizeCriterionAllCVOmp), #endif - std::make_pair(IParallelalbe::ParallelType::CUDA, &GwmMultiscaleGWRAlgorithm::mBandwidthSizeCriterionAllCVSerial) + std::make_pair(gwm::ParallelType::CUDA, &GwmMultiscaleGWRAlgorithm::mBandwidthSizeCriterionAllCVSerial) }), - std::make_pair >(BandwidthSelectionCriterionType::AIC, { - std::make_pair(IParallelalbe::ParallelType::SerialOnly, &GwmMultiscaleGWRAlgorithm::mBandwidthSizeCriterionAllAICSerial), + std::make_pair >(BandwidthSelectionCriterionType::AIC, { + std::make_pair(gwm::ParallelType::SerialOnly, &GwmMultiscaleGWRAlgorithm::mBandwidthSizeCriterionAllAICSerial), #ifdef ENABLE_OpenMP std::make_pair(IParallelalbe::ParallelType::OpenMP, &GwmMultiscaleGWRAlgorithm::mBandwidthSizeCriterionAllAICOmp), #endif - std::make_pair(IParallelalbe::ParallelType::CUDA, &GwmMultiscaleGWRAlgorithm::mBandwidthSizeCriterionAllAICSerial) + std::make_pair(gwm::ParallelType::CUDA, &GwmMultiscaleGWRAlgorithm::mBandwidthSizeCriterionAllAICSerial) }) }; return mapper[type][mParallelType]; @@ -1311,63 +1311,29 @@ GwmMultiscaleGWRAlgorithm::BandwidthSizeCriterionFunction GwmMultiscaleGWRAlgori GwmMultiscaleGWRAlgorithm::BandwidthSizeCriterionFunction GwmMultiscaleGWRAlgorithm::bandwidthSizeCriterionVar(GwmMultiscaleGWRAlgorithm::BandwidthSelectionCriterionType type) { - QMap > mapper = { - std::make_pair >(BandwidthSelectionCriterionType::CV, { - std::make_pair(IParallelalbe::ParallelType::SerialOnly, &GwmMultiscaleGWRAlgorithm::mBandwidthSizeCriterionVarCVSerial), + QMap > mapper = { + std::make_pair >(BandwidthSelectionCriterionType::CV, { + std::make_pair(gwm::ParallelType::SerialOnly, &GwmMultiscaleGWRAlgorithm::mBandwidthSizeCriterionVarCVSerial), #ifdef ENABLE_OpenMP std::make_pair(IParallelalbe::ParallelType::OpenMP, &GwmMultiscaleGWRAlgorithm::mBandwidthSizeCriterionVarCVOmp), #endif - std::make_pair(IParallelalbe::ParallelType::CUDA, &GwmMultiscaleGWRAlgorithm::mBandwidthSizeCriterionVarCVSerial) + std::make_pair(gwm::ParallelType::CUDA, &GwmMultiscaleGWRAlgorithm::mBandwidthSizeCriterionVarCVSerial) }), - std::make_pair >(BandwidthSelectionCriterionType::AIC, { - std::make_pair(IParallelalbe::ParallelType::SerialOnly, &GwmMultiscaleGWRAlgorithm::mBandwidthSizeCriterionVarAICSerial), + std::make_pair >(BandwidthSelectionCriterionType::AIC, { + std::make_pair(gwm::ParallelType::SerialOnly, &GwmMultiscaleGWRAlgorithm::mBandwidthSizeCriterionVarAICSerial), #ifdef ENABLE_OpenMP std::make_pair(IParallelalbe::ParallelType::OpenMP, &GwmMultiscaleGWRAlgorithm::mBandwidthSizeCriterionVarAICOmp), #endif - std::make_pair(IParallelalbe::ParallelType::CUDA, &GwmMultiscaleGWRAlgorithm::mBandwidthSizeCriterionVarAICSerial) + std::make_pair(gwm::ParallelType::CUDA, &GwmMultiscaleGWRAlgorithm::mBandwidthSizeCriterionVarAICSerial) }) }; return mapper[type][mParallelType]; } -void GwmMultiscaleGWRAlgorithm::setParallelType(const IParallelalbe::ParallelType &type) +void GwmMultiscaleGWRAlgorithm::setParallelType(const gwm::ParallelType &type) { - if (parallelAbility() & type) - { - mParallelType = type; - - // 转换并行类型 - gwm::ParallelType gwmType = gwm::ParallelType::SerialOnly; - if (type == IParallelalbe::OpenMP) - { - gwmType = gwm::ParallelType::OpenMP; - } - - // 设置到内核库 - if (mMGWRCore) - { - mMGWRCore->setParallelType(gwmType); - } - - switch (type) { - case IParallelalbe::ParallelType::SerialOnly: - mRegressionAll = &GwmMultiscaleGWRAlgorithm::regressionAllSerial; - mRegressionVar = &GwmMultiscaleGWRAlgorithm::regressionVarSerial; - break; -#ifdef ENABLE_OpenMP - case IParallelalbe::ParallelType::OpenMP: - mRegressionAll = &GwmMultiscaleGWRAlgorithm::regressionAllOmp; - mRegressionVar = &GwmMultiscaleGWRAlgorithm::regressionVarOmp; - break; -#endif -// case IParallelalbe::ParallelType::CUDA: -// mRegressionAll = &GwmMultiscaleGWRAlgorithm::regressionAllOmp; -// mRegressionVar = &GwmMultiscaleGWRAlgorithm::regressionVarOmp; -// break; - default: - break; - } - } + mParallelType = type; + mMGWRCore->setParallelType(type); } void GwmMultiscaleGWRAlgorithm::setSpatialWeights(const QList &spatialWeights) diff --git a/src/TaskThread/gwmmultiscalegwralgorithm.h b/src/TaskThread/gwmmultiscalegwralgorithm.h index f83b214..2d2be1c 100644 --- a/src/TaskThread/gwmmultiscalegwralgorithm.h +++ b/src/TaskThread/gwmmultiscalegwralgorithm.h @@ -7,6 +7,7 @@ #include "iparallelable.h" #include "gwmbasicgwralgorithm.h" +#include #include #include "gwmodel.h" @@ -14,7 +15,7 @@ //using namespace gwm; //using namespace arma; -class GwmMultiscaleGWRAlgorithm : public GwmSpatialMultiscaleAlgorithm, public IRegressionAnalysis, public IBandwidthSizeSelectable, public IOpenmpParallelable +class GwmMultiscaleGWRAlgorithm : public GwmSpatialMultiscaleAlgorithm, public IRegressionAnalysis, public IBandwidthSizeSelectable, public gwm::IParallelizable, public gwm::IParallelOpenmpEnabled, public gwm::IParallelCudaEnabled { Q_OBJECT @@ -156,13 +157,17 @@ class GwmMultiscaleGWRAlgorithm : public GwmSpatialMultiscaleAlgorithm, public I public: // IParallelalbe interface int parallelAbility() const override; - ParallelType parallelType() const override; - void setParallelType(const ParallelType &type) override; + gwm::ParallelType parallelType() const override; + void setParallelType(const gwm::ParallelType &type) override; public: // IOpenmpParallelable interface void setOmpThreadNum(const int threadNum) override; +public: // ICudaParallelable interface + void setGPUId(const int gpuId) override; + void setGroupSize(const std::size_t groupSize) override; + void setCanceled(bool canceled) override; protected: @@ -252,8 +257,10 @@ class GwmMultiscaleGWRAlgorithm : public GwmSpatialMultiscaleAlgorithm, public I GwmDiagnostic mDiagnostic; - IParallelalbe::ParallelType mParallelType = IParallelalbe::SerialOnly; + gwm::ParallelType mParallelType = gwm::SerialOnly; int mOmpThreadNum = 8; + int mGPUId = 0; + std::size_t mGroupSize = 64; public: static int treeChildCount; @@ -420,7 +427,7 @@ inline int GwmMultiscaleGWRAlgorithm::parallelAbility() const ; } -inline IParallelalbe::ParallelType GwmMultiscaleGWRAlgorithm::parallelType() const +inline gwm::ParallelType GwmMultiscaleGWRAlgorithm::parallelType() const { return mParallelType; } @@ -430,6 +437,17 @@ inline void GwmMultiscaleGWRAlgorithm::setOmpThreadNum(const int threadNum) mOmpThreadNum = threadNum; } +inline void GwmMultiscaleGWRAlgorithm::setGPUId(const int gpuId) +{ + mGPUId = gpuId; +} + +inline void GwmMultiscaleGWRAlgorithm::setGroupSize(const std::size_t groupSize) +{ + Q_ASSERT(groupSize <= static_cast(std::numeric_limits::max())); + mGroupSize = groupSize; +} + inline bool GwmMultiscaleGWRAlgorithm::OLS() const { return mOLS; diff --git a/src/TaskThread/gwmrobustgwralgorithm.cpp b/src/TaskThread/gwmrobustgwralgorithm.cpp index 7ec099c..e9a3bec 100644 --- a/src/TaskThread/gwmrobustgwralgorithm.cpp +++ b/src/TaskThread/gwmrobustgwralgorithm.cpp @@ -5,7 +5,7 @@ #ifdef ENABLE_OpenMP #include #endif - +#include int GwmRobustGWRAlgorithm::treeChildCount = 0; GwmRobustGWRAlgorithm::GwmRobustGWRAlgorithm(): GwmBasicGWRAlgorithm(), @@ -56,19 +56,16 @@ void GwmRobustGWRAlgorithm::run() emit message("Regression ..."); mRGWRCore->setParallelType(mParallelType); mRGWRCore->setOmpThreadNum(mOmpThreadNum); - qDebug() << "core parallelType =" << mRGWRCore->parallelType(); - qDebug() << "core parallelAbility =" << mRGWRCore->parallelAbility(); mRGWRCore->setTelegram(std::make_unique(this)); - - QElapsedTimer timer; - timer.start(); - + qDebug() << "mParallelType:" << static_cast(mParallelType) + << "-> mRGWRCore parallelType:" << static_cast(mRGWRCore->parallelType()) + << "parallelAbility:" << static_cast(mRGWRCore->parallelAbility()); + auto start_time = std::chrono::high_resolution_clock::now(); mBetas = mRGWRCore->fit(); - - qint64 elapsed = timer.elapsed(); - qDebug() << "fit() time =" << elapsed << "ms"; - - // qDebug() << "mBetas:"; mBetas.print(); + auto end_time = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast(end_time - start_time); + qDebug() << "fit() execution time:" << duration.count() << "ms, Threads:" << mOmpThreadNum; + qDebug() << "mBetas:"; mBetas.print(); } if(mOLS&&!checkCanceled()){ @@ -269,7 +266,29 @@ void GwmRobustGWRAlgorithm::createResultLayer(CreateResultLayerData data) void GwmRobustGWRAlgorithm::setParallelType(const gwm::ParallelType &type) { - // GwmBasicGWRAlgorithm::setParallelType(type); + GwmBasicGWRAlgorithm::setParallelType(type); + if (type & parallelAbility()) + { + mParallelType = type; + switch (type) { + case gwm::ParallelType::SerialOnly: + mRegressionHatmatrixFunction = &GwmRobustGWRAlgorithm::regressionHatmatrixSerial; + break; +#ifdef ENABLE_OpenMP + case gwm::ParallelType::OpenMP: + mRegressionHatmatrixFunction = &GwmRobustGWRAlgorithm::regressionHatmatrixOmp; + break; +#endif +#ifdef ENABLE_CUDA + case gwm::ParallelType::CUDA: + mRegressionHatmatrixFunction = &GwmRobustGWRAlgorithm::regressionHatmatrixCuda; + break; +#endif + default: + mRegressionHatmatrixFunction = &GwmRobustGWRAlgorithm::regressionHatmatrixSerial; + break; + } + } } mat GwmRobustGWRAlgorithm::robustGWRCaliFirst(const mat &x, const vec &y, mat &betasSE, vec &shat, vec &qDiag, mat &S) @@ -435,22 +454,22 @@ mat GwmRobustGWRAlgorithm::regressionHatmatrixCuda(const mat &x, const vec &y, m bool longlat = false; if (mSpatialWeight.distance()->type() == GwmDistance::MinkwoskiDistance) { - GwmMinkwoskiDistance* d = mSpatialWeight.distance(); - p = d->poly(); - theta = d->theta(); + gwm::MinkwoskiDistance& d = mSpatialWeight.distance(); + p = d.poly(); + theta = d.theta(); } else if (mSpatialWeight.distance()->type() == GwmDistance::CRSDistance) { - GwmCRSDistance* d = mSpatialWeight.distance(); - longlat = d->geographic(); + gwm::CRSDistance& d = mSpatialWeight.distance(); + longlat = d.geographic(); } - GwmBandwidthWeight* bw = mSpatialWeight.weight(); - bool adaptive = bw->adaptive(); + gwm::BandwidthWeight& bw = mSpatialWeight.weight(); + bool adaptive = bw.adaptive(); for(int i=0;iSetWeightMask(i,mWeightMask(i)); } - bool gwrStatus = cuda->Regression(true, p, theta, longlat, bw->bandwidth(), bw->kernel(), adaptive, mGroupSize, mGpuId); + bool gwrStatus = cuda->Regression(true, p, theta, longlat, bw.bandwidth(), bw.kernel(), adaptive, mGroupSize, mGpuId); mat betas(nVar, nDp, fill::zeros); betasSE = mat(nVar, nDp, fill::zeros); shat = vec(2, fill::zeros); diff --git a/src/TaskThread/gwmscalablegwralgorithm.cpp b/src/TaskThread/gwmscalablegwralgorithm.cpp index c3aa810..c82c706 100644 --- a/src/TaskThread/gwmscalablegwralgorithm.cpp +++ b/src/TaskThread/gwmscalablegwralgorithm.cpp @@ -224,7 +224,7 @@ void GwmScalableGWRAlgorithm::run() // findDataPointNeighbours(); } - qDebug() << "Bandwidth:" << mSpatialWeight.weight()->bandwidth(); + qDebug() << "Bandwidth:" << mSpatialWeight.weight().bandwidth(); qDebug() << "Before mSGWRCore->fit()"; arma::mat betas = mSGWRCore->fit(); qDebug() << "After mSGWRCore->fit(), betas size:" << betas.n_rows << betas.n_cols; @@ -316,8 +316,8 @@ void GwmScalableGWRAlgorithm::run() void GwmScalableGWRAlgorithm::findDataPointNeighbours() { - gwm::BandwidthWeight* bandwidth = mDpSpatialWeight.weight(); - uword nDp = mDataPoints.n_rows, nBw = bandwidth->bandwidth() < nDp ? bandwidth->bandwidth() : nDp; + gwm::BandwidthWeight& bandwidth = mDpSpatialWeight.weight(); + uword nDp = mDataPoints.n_rows, nBw = bandwidth.bandwidth() < nDp ? bandwidth.bandwidth() : nDp; if (mParameterOptimizeCriterion == ParameterOptimizeCriterionType::CV) { nBw -= 1; @@ -348,10 +348,10 @@ void GwmScalableGWRAlgorithm::findDataPointNeighbours() mat GwmScalableGWRAlgorithm::findNeighbours(const gwm::SpatialWeight &spatialWeight, umat &nnIndex) { - gwm::BandwidthWeight* bandwidth = spatialWeight.weight(); + gwm::BandwidthWeight& bandwidth = spatialWeight.weight(); uword nRp = spatialWeight.distance()->distance(0).n_elem; uword nDp = mDpSpatialWeight.distance()->distance(0).n_elem; - uword nBw = bandwidth->bandwidth() < nDp ? bandwidth->bandwidth() : nDp; + uword nBw = bandwidth.bandwidth() < nDp ? bandwidth.bandwidth() : nDp; umat index(nBw, nRp, fill::zeros); mat dists(nBw, nRp, fill::zeros); for (uword i = 0; i < nRp && !checkCanceled(); i++) @@ -392,7 +392,7 @@ double scagwr_aic_multimin_function0(const gsl_vector* vars, void* params) double GwmScalableGWRAlgorithm::optimize(const mat &Mx0, const mat &My0, double& b_tilde, double& alpha) { - GwmBandwidthWeight* bandwidth = mSpatialWeight.weight(); + gwm::BandwidthWeight& bandwidth = mSpatialWeight.weight(); gsl_multimin_fminimizer* minizer = gsl_multimin_fminimizer_alloc(gsl_multimin_fminimizer_nmsimplex, 2); gsl_vector* target = gsl_vector_alloc(2); gsl_vector_set(target, 0, b_tilde); @@ -400,7 +400,7 @@ double GwmScalableGWRAlgorithm::optimize(const mat &Mx0, const mat &My0, double& gsl_vector* step = gsl_vector_alloc(2); gsl_vector_set(step, 0, 0.01); gsl_vector_set(step, 1, 0.01); - LoocvParams params = { &mX, &mY, (int)bandwidth->bandwidth(), mPolynomial, &Mx0, &My0 }; + LoocvParams params = { &mX, &mY, (int)bandwidth.bandwidth(), mPolynomial, &Mx0, &My0 }; gsl_multimin_function function = { mParameterOptimizeCriterion == CV ? &scagwr_loocv_multimin_function0 : &scagwr_aic_multimin_function0, 2, ¶ms }; double cv = DBL_MAX; int status = gsl_multimin_fminimizer_set(minizer, &function, target, step); @@ -475,13 +475,13 @@ void GwmScalableGWRAlgorithm::prepare() mat GwmScalableGWRAlgorithm::regressionSerial(const arma::mat &x, const arma::vec &y) { - gwm::BandwidthWeight* bandwidth = mSpatialWeight.weight(); - arma::uword nDp = mDataPoints.n_rows, nRp = mRegressionPoints.n_rows, nVar = mX.n_cols, nBw = bandwidth->bandwidth(); + gwm::BandwidthWeight& bandwidth = mSpatialWeight.weight(); + arma::uword nDp = mDataPoints.n_rows, nRp = mRegressionPoints.n_rows, nVar = mX.n_cols, nBw = bandwidth.bandwidth(); double band0 = 0.0; mat G0; umat rpNNIndex; mat rpNNDists = findNeighbours(mSpatialWeight, rpNNIndex); - switch (bandwidth->kernel()) + switch (bandwidth.kernel()) { case gwm::BandwidthWeight::KernelFunctionType::Gaussian: band0 = median(rpNNDists.col(qMin(50, nBw) - 1)) / sqrt(3); @@ -576,8 +576,8 @@ mat GwmScalableGWRAlgorithm::regressionSerial(const arma::mat &x, const arma::ve arma::mat GwmScalableGWRAlgorithm::regressionHatmatrixSerial(const arma::mat &x, const arma::vec &y) { - GwmBandwidthWeight* bandwidth = mSpatialWeight.weight(); - int bw = bandwidth->bandwidth(); + gwm::BandwidthWeight& bandwidth = mSpatialWeight.weight(); + int bw = bandwidth.bandwidth(); int n = x.n_rows, k = x.n_cols, poly1 = mPolynomial + 1; double b = mScale, a = mPenalty; mat XtX = x.t() * x, XtY = x.t() * y; @@ -586,13 +586,13 @@ arma::mat GwmScalableGWRAlgorithm::regressionHatmatrixSerial(const arma::mat &x, double band0 = 0.0; umat dpNNIndex; mat dpNNDists = findNeighbours(mDpSpatialWeight, dpNNIndex); - switch (bandwidth->kernel()) + switch (bandwidth.kernel()) { - case GwmBandwidthWeight::KernelFunctionType::Gaussian: + case gwm::BandwidthWeight::KernelFunctionType::Gaussian: band0 = median(dpNNDists.col(qMin(50, bw) - 1)) / sqrt(3); mG0 = exp(-pow(dpNNDists / band0, 2)); break; - case GwmBandwidthWeight::KernelFunctionType::Exponential: + case gwm::BandwidthWeight::KernelFunctionType::Exponential: band0 = median(dpNNDists.col(qMin(50, bw) - 1)) / 3; mG0 = exp(-pow(dpNNDists / band0, 2)); break; @@ -698,23 +698,17 @@ arma::mat GwmScalableGWRAlgorithm::regressionHatmatrixSerial(const arma::mat &x, void GwmScalableGWRAlgorithm::initPoints() { GwmGeographicalWeightedRegressionAlgorithm::initPoints(); - if (mDpSpatialWeight.distance()->type() == gwm::Distance::CRSDistance || mDpSpatialWeight.distance()->type() == gwm::Distance::MinkwoskiDistance) + if (mDpSpatialWeight.distance()->type() == gwm::Distance::DistanceType::CRSDistance || mDpSpatialWeight.distance()->type() == gwm::Distance::DistanceType::MinkwoskiDistance) { - if (mDpSpatialWeight.distance()->type() == gwm::Distance::CRSDistance) + if (mDpSpatialWeight.distance()->type() == gwm::Distance::DistanceType::CRSDistance) { - auto* d = mDpSpatialWeight.distance(); - if (d) - { - d->makeParameter({ mDataPoints, mDataPoints }); - } + auto& d = mDpSpatialWeight.distance(); + d.makeParameter({ mDataPoints, mDataPoints }); } - else if (mDpSpatialWeight.distance()->type() == gwm::Distance::MinkwoskiDistance) + else if (mDpSpatialWeight.distance()->type() == gwm::Distance::DistanceType::MinkwoskiDistance) { - auto* d2 = mDpSpatialWeight.distance(); - if (d2) - { - d2->makeParameter({ mDataPoints, mDataPoints }); - } + auto& d2 = mDpSpatialWeight.distance(); + d2.makeParameter({ mDataPoints, mDataPoints }); } } } @@ -840,11 +834,11 @@ bool GwmScalableGWRAlgorithm::isValid() { if (GwmGeographicalWeightedRegressionAlgorithm::isValid()) { - gwm::BandwidthWeight* bandwidth = mSpatialWeight.weight(); - if (!(bandwidth->kernel() == gwm::BandwidthWeight::Gaussian || bandwidth->kernel() == gwm::BandwidthWeight::Exponential)) + gwm::BandwidthWeight& bandwidth = mSpatialWeight.weight(); + if (!(bandwidth.kernel() == gwm::BandwidthWeight::Gaussian || bandwidth.kernel() == gwm::BandwidthWeight::Exponential)) return false; - if (bandwidth->bandwidth() <= mIndepVars.size()) + if (bandwidth.bandwidth() <= mIndepVars.size()) return false; return true; diff --git a/src/TaskThread/gwmswimtaskthread.cpp b/src/TaskThread/gwmswimtaskthread.cpp index b19cf4c..e0b2ebc 100644 --- a/src/TaskThread/gwmswimtaskthread.cpp +++ b/src/TaskThread/gwmswimtaskthread.cpp @@ -1,4 +1,4 @@ -#include "gwmswimtaskthread.h" +#include "gwmswimtaskthread.h" #include "SpatialWeight/gwmbandwidthweight.h" #include "SpatialWeight/gwmcrsdistance.h" #include diff --git a/src/gwmggwroptionsdialog.cpp b/src/gwmggwroptionsdialog.cpp index 4eb8282..24ed53d 100644 --- a/src/gwmggwroptionsdialog.cpp +++ b/src/gwmggwroptionsdialog.cpp @@ -1,5 +1,8 @@ #include "gwmggwroptionsdialog.h" #include "ui_gwmggwroptionsdialog.h" +#ifdef ENABLE_OPENMP +#include +#endif #include #include #include @@ -59,8 +62,14 @@ GwmGGWROptionsDialog::GwmGGWROptionsDialog(QList originItemL calcParallelTypeBtnGroup->addButton(ui->mCalcParallelNoneRadio); calcParallelTypeBtnGroup->addButton(ui->mCalcParallelMultithreadRadio); calcParallelTypeBtnGroup->addButton(ui->mCalcParallelGPURadio); +#ifdef ENABLE_OPENMP + int cores = omp_get_num_procs(); + if (cores <= 0) cores = 8; + ui->mThreadNum->setValue(cores); + ui->mThreadNum->setMaximum(cores); +#endif connect(ui->mCalcParallelNoneRadio, &QAbstractButton::toggled, this, &GwmGGWROptionsDialog::onNoneRadioToggled); -#ifdef ENABLE_OpenMP +#ifdef ENABLE_OPENMP connect(ui->mCalcParallelMultithreadRadio, &QAbstractButton::toggled, this, &GwmGGWROptionsDialog::onMultithreadingRadioToggled); #else ui->mCalcParallelMultithreadRadio->setEnabled(false); diff --git a/src/gwmggwroptionsdialog.ui b/src/gwmggwroptionsdialog.ui index 1b45659..bac442c 100644 --- a/src/gwmggwroptionsdialog.ui +++ b/src/gwmggwroptionsdialog.ui @@ -762,6 +762,9 @@ + + false + 0 diff --git a/src/gwmgtdroptionsdialog.cpp b/src/gwmgtdroptionsdialog.cpp index aed7928..6ddbe83 100644 --- a/src/gwmgtdroptionsdialog.cpp +++ b/src/gwmgtdroptionsdialog.cpp @@ -1,6 +1,6 @@ #include "gwmgtdroptionsdialog.h" #include "ui_gwmgtdroptionsdialog.h" -#ifdef ENABLE_OpenMP +#ifdef ENABLE_OPENMP #include #endif #include @@ -82,7 +82,7 @@ GwmGTDROptionsDialog::GwmGTDROptionsDialog(QList originItemL calcParallelTypeBtnGroup->addButton(ui->mCalcParallelNoneRadio); calcParallelTypeBtnGroup->addButton(ui->mCalcParallelMultithreadRadio); // calcParallelTypeBtnGroup->addButton(ui->mCalcParallelGPURadio); -#ifdef ENABLE_OpenMP +#ifdef ENABLE_OPENMP int cores = omp_get_num_procs(); ui->mThreadNum->setValue(cores); ui->mThreadNum->setMaximum(cores); diff --git a/src/gwmgtdroptionsdialog.ui b/src/gwmgtdroptionsdialog.ui index 403b836..02f7e6c 100644 --- a/src/gwmgtdroptionsdialog.ui +++ b/src/gwmgtdroptionsdialog.ui @@ -614,6 +614,9 @@ + + false + 0 diff --git a/src/gwmgtwroptionsdialog.cpp b/src/gwmgtwroptionsdialog.cpp index 2bc90d6..bd00222 100644 --- a/src/gwmgtwroptionsdialog.cpp +++ b/src/gwmgtwroptionsdialog.cpp @@ -1,6 +1,6 @@ #include "gwmgtwroptionsdialog.h" #include "ui_gwmgtwroptionsdialog.h" -#ifdef ENABLE_OpenMP +#ifdef ENABLE_OPENMP #include #endif #include @@ -64,7 +64,7 @@ GwmGTWROptionsDialog::GwmGTWROptionsDialog(QList originItemL double initialLambda = (1.0 * ui->sldTimeLambda->value()) / 100.0; ui->lblLambda->setText(QString("Lambda: %1").arg(initialLambda, 0, 'f', 2)); -#ifdef ENABLE_OpenMP +#ifdef ENABLE_OPENMP int cores = omp_get_num_procs(); ui->mThreadNum->setValue(cores); ui->mThreadNum->setMaximum(cores); @@ -516,16 +516,16 @@ void GwmGTWROptionsDialog::updateFields() // 并行设置 if (ui->mCalcParallelNoneRadio->isChecked()) { - mTaskThread->setParallelType(IParallelalbe::SerialOnly); + mTaskThread->setParallelType(gwm::SerialOnly); } else if (ui->mCalcParallelMultithreadRadio->isChecked()) { - mTaskThread->setParallelType(IParallelalbe::OpenMP); + mTaskThread->setParallelType(gwm::OpenMP); mTaskThread->setOmpThreadNum(ui->mThreadNum->value()); } else { - mTaskThread->setParallelType(IParallelalbe::SerialOnly); + mTaskThread->setParallelType(gwm::SerialOnly); } // 其他设置 mTaskThread->setHasHatMatrix(ui->cbxHatmatrix->isChecked()); diff --git a/src/gwmgwcorrelationoptionsdialog.cpp b/src/gwmgwcorrelationoptionsdialog.cpp index deca301..f494020 100644 --- a/src/gwmgwcorrelationoptionsdialog.cpp +++ b/src/gwmgwcorrelationoptionsdialog.cpp @@ -1,6 +1,6 @@ #include "gwmgwcorrelationoptionsdialog.h" #include "ui_gwmgwcorrelationoptionsdialog.h" -#ifdef ENABLE_OpenMP +#ifdef ENABLE_OPENMP #include #endif #include @@ -82,7 +82,7 @@ GwmGWCorrelationOptionsDialog::GwmGWCorrelationOptionsDialog(QListaddButton(ui->mCalcParallelNoneRadio); calcParallelTypeBtnGroup->addButton(ui->mCalcParallelMultithreadRadio); // calcParallelTypeBtnGroup->addButton(ui->mCalcParallelGPURadio); -#ifdef ENABLE_OpenMP +#ifdef ENABLE_OPENMP int cores = omp_get_num_procs(); ui->mThreadNum->setValue(cores); ui->mThreadNum->setMaximum(cores); diff --git a/src/gwmgwpcaoptionsdialog.cpp b/src/gwmgwpcaoptionsdialog.cpp index 911cf6e..93f5cd8 100644 --- a/src/gwmgwpcaoptionsdialog.cpp +++ b/src/gwmgwpcaoptionsdialog.cpp @@ -1,6 +1,6 @@ #include "gwmgwpcaoptionsdialog.h" #include "ui_gwmgwpcaoptionsdialog.h" -#ifdef ENABLE_OpenMP +#ifdef ENABLE_OPENMP #include #endif #include @@ -63,7 +63,7 @@ GwmGWPCAOptionsDialog::GwmGWPCAOptionsDialog(QList originIte calcParallelTypeBtnGroup->addButton(ui->mCalcParallelNoneRadio); calcParallelTypeBtnGroup->addButton(ui->mCalcParallelMultithreadRadio); calcParallelTypeBtnGroup->addButton(ui->mCalcParallelGPURadio); -#ifdef ENABLE_OpenMP +#ifdef ENABLE_OPENMP int cores = omp_get_num_procs(); ui->mThreadNum->setValue(cores); ui->mThreadNum->setMaximum(cores); diff --git a/src/gwmgwpcaoptionsdialog.ui b/src/gwmgwpcaoptionsdialog.ui index d543e85..6bfc8ed 100644 --- a/src/gwmgwpcaoptionsdialog.ui +++ b/src/gwmgwpcaoptionsdialog.ui @@ -656,6 +656,9 @@ + + false + 0 diff --git a/src/gwmgwroptionsdialog.cpp b/src/gwmgwroptionsdialog.cpp index 2e81693..dabefb3 100644 --- a/src/gwmgwroptionsdialog.cpp +++ b/src/gwmgwroptionsdialog.cpp @@ -8,7 +8,7 @@ #include #include -#ifdef ENABLE_OpenMP +#ifdef ENABLE_OPENMP #include #endif @@ -72,7 +72,7 @@ GwmGWROptionsDialog::GwmGWROptionsDialog(QList originItemLis connect(ui->mCalcParallelNoneRadio, &QAbstractButton::toggled, this, &GwmGWROptionsDialog::onNoneRadioToggled); connect(ui->mCalcParallelMultithreadRadio, &QAbstractButton::toggled, this, &GwmGWROptionsDialog::onMultithreadingRadioToggled); connect(ui->mCalcParallelGPURadio, &QAbstractButton::toggled, this, &GwmGWROptionsDialog::onGPURadioToggled); -#ifdef ENABLE_OpenMP +#ifdef ENABLE_OPENMP int cores = omp_get_num_procs(); ui->mThreadNum->setValue(cores); ui->mThreadNum->setMaximum(cores); diff --git a/src/gwmgwroptionsdialog.ui b/src/gwmgwroptionsdialog.ui index ed420ed..549a3a3 100644 --- a/src/gwmgwroptionsdialog.ui +++ b/src/gwmgwroptionsdialog.ui @@ -699,6 +699,9 @@ + + false + 0 diff --git a/src/gwmlcrgwroptionsdialog.cpp b/src/gwmlcrgwroptionsdialog.cpp index 0610fac..354c20c 100644 --- a/src/gwmlcrgwroptionsdialog.cpp +++ b/src/gwmlcrgwroptionsdialog.cpp @@ -8,7 +8,7 @@ #include #include -#ifdef ENABLE_OpenMP +#ifdef ENABLE_OPENMP #include #endif @@ -63,7 +63,7 @@ GwmLcrGWROptionsDialog::GwmLcrGWROptionsDialog(QList originI calcParallelTypeBtnGroup->addButton(ui->mCalcParallelNoneRadio); calcParallelTypeBtnGroup->addButton(ui->mCalcParallelMultithreadRadio); calcParallelTypeBtnGroup->addButton(ui->mCalcParallelGPURadio); -#ifdef ENABLE_OpenMP +#ifdef ENABLE_OPENMP int cores = omp_get_num_procs(); ui->mThreadNum->setValue(cores); ui->mThreadNum->setMaximum(cores); @@ -498,11 +498,11 @@ void GwmLcrGWROptionsDialog::updateFields() // 并行设置 if (ui->mCalcParallelNoneRadio->isChecked()) { - mTaskThread->setParallelType(gwm::SerialOnly); + mTaskThread->setParallelType(IParallelalbe::SerialOnly); } else if (ui->mCalcParallelMultithreadRadio->isChecked()) { - mTaskThread->setParallelType(gwm::OpenMP); + mTaskThread->setParallelType(IParallelalbe::OpenMP); mTaskThread->setOmpThreadNum(ui->mThreadNum->value()); } // 其他设置 diff --git a/src/gwmlcrgwroptionsdialog.ui b/src/gwmlcrgwroptionsdialog.ui index daaf5d9..78e4f5c 100644 --- a/src/gwmlcrgwroptionsdialog.ui +++ b/src/gwmlcrgwroptionsdialog.ui @@ -661,6 +661,9 @@ + + false + 0 diff --git a/src/gwmmultiscalegwroptionsdialog.cpp b/src/gwmmultiscalegwroptionsdialog.cpp index e1d9dec..e09f5c2 100644 --- a/src/gwmmultiscalegwroptionsdialog.cpp +++ b/src/gwmmultiscalegwroptionsdialog.cpp @@ -1,6 +1,6 @@ -#include "gwmmultiscalegwroptionsdialog.h" +#include "gwmmultiscalegwroptionsdialog.h" #include "ui_gwmmultiscalegwroptionsdialog.h" -#ifdef ENABLE_OpenMP +#ifdef ENABLE_OPENMP #include #endif #include @@ -86,7 +86,7 @@ GwmMultiscaleGWROptionsDialog::GwmMultiscaleGWROptionsDialog(QListaddButton(ui->mCalcParallelNoneRadio); calcParallelTypeBtnGroup->addButton(ui->mCalcParallelMultithreadRadio); // calcParallelTypeBtnGroup->addButton(ui->mCalcParallelGPURadio); -#ifdef ENABLE_OpenMP +#ifdef ENABLE_OPENMP int cores = omp_get_num_procs(); ui->mThreadNum->setValue(cores); ui->mThreadNum->setMaximum(cores); @@ -713,20 +713,20 @@ void GwmMultiscaleGWROptionsDialog::updateFields() // 并行设置 if (ui->mCalcParallelNoneRadio->isChecked()) { - mTaskThread->setParallelType(IParallelalbe::SerialOnly); + mTaskThread->setParallelType(gwm::SerialOnly); } else if (ui->mCalcParallelMultithreadRadio->isChecked()) { - mTaskThread->setParallelType(IParallelalbe::OpenMP); + mTaskThread->setParallelType(gwm::OpenMP); mTaskThread->setOmpThreadNum(ui->mThreadNum->value()); } else if (ui->mCalcParallelGPURadio->isChecked() && !ui->mDistTypeDmatRadio->isChecked()) { - mTaskThread->setParallelType(IParallelalbe::CUDA); + mTaskThread->setParallelType(gwm::CUDA); } else { - mTaskThread->setParallelType(IParallelalbe::SerialOnly); + mTaskThread->setParallelType(gwm::SerialOnly); } // 其他设置 mTaskThread->setHasHatMatrix(ui->cbxHatmatrix->isChecked()); diff --git a/src/gwmmultiscalegwroptionsdialog.ui b/src/gwmmultiscalegwroptionsdialog.ui index 3b86283..3feb36e 100644 --- a/src/gwmmultiscalegwroptionsdialog.ui +++ b/src/gwmmultiscalegwroptionsdialog.ui @@ -844,6 +844,9 @@ + + false + false diff --git a/src/gwmrobustgwroptionsdialog.cpp b/src/gwmrobustgwroptionsdialog.cpp index 7b79238..7159d3e 100644 --- a/src/gwmrobustgwroptionsdialog.cpp +++ b/src/gwmrobustgwroptionsdialog.cpp @@ -8,7 +8,7 @@ #include #include -#ifdef ENABLE_OpenMP +#ifdef ENABLE_OPENMP #include #endif @@ -64,7 +64,7 @@ GwmRobustGWROptionsDialog::GwmRobustGWROptionsDialog(QList o connect(ui->mCalcParallelNoneRadio, &QAbstractButton::toggled, this, &GwmRobustGWROptionsDialog::onNoneRadioToggled); connect(ui->mCalcParallelMultithreadRadio, &QAbstractButton::toggled, this, &GwmRobustGWROptionsDialog::onMultithreadingRadioToggled); connect(ui->mCalcParallelGPURadio, &QAbstractButton::toggled, this, &GwmRobustGWROptionsDialog::onGPURadioToggled); -#ifdef ENABLE_OpenMP +#ifdef ENABLE_OPENMP int cores = omp_get_num_procs(); ui->mThreadNum->setValue(cores); ui->mThreadNum->setMaximum(cores); diff --git a/src/gwmrobustgwroptionsdialog.ui b/src/gwmrobustgwroptionsdialog.ui index f6b32d4..3b403f6 100644 --- a/src/gwmrobustgwroptionsdialog.ui +++ b/src/gwmrobustgwroptionsdialog.ui @@ -603,6 +603,9 @@ + + false + 0 diff --git a/src/gwmswimoptionsdialog.cpp b/src/gwmswimoptionsdialog.cpp index b07fcc3..bc2223b 100644 --- a/src/gwmswimoptionsdialog.cpp +++ b/src/gwmswimoptionsdialog.cpp @@ -1,4 +1,4 @@ -#include "gwmswimoptionsdialog.h" +#include "gwmswimoptionsdialog.h" #include "ui_gwmswimoptionsdialog.h" #include #include @@ -17,7 +17,7 @@ #include #include #include -#ifdef ENABLE_OpenMP +#ifdef ENABLE_OPENMP #include #endif @@ -90,7 +90,7 @@ GwmSWIMOptionsDialog::GwmSWIMOptionsDialog(QWidget *parent) : calcParallelTypeBtnGroup->addButton(ui->mCalcParallelMultithreadRadio); calcParallelTypeBtnGroup->addButton(ui->mCalcParallelGPURadio); ui->mCalcParallelNoneRadio->setChecked(true); -#ifdef ENABLE_OpenMP +#ifdef ENABLE_OPENMP int cores = omp_get_num_procs(); ui->mThreadNum->setValue(cores); ui->mThreadNum->setMaximum(cores); diff --git a/src/gwmswimoptionsdialog.ui b/src/gwmswimoptionsdialog.ui index 2111a62..ecdc4ec 100644 --- a/src/gwmswimoptionsdialog.ui +++ b/src/gwmswimoptionsdialog.ui @@ -719,6 +719,9 @@ + + false + GPU