Program Listing for File GWRBasic.h

Return to documentation for file (include/gwmodelpp/GWRBasic.h)

#ifndef GWRBASIC_H
#define GWRBASIC_H

#include <utility>
#include <string>
#include <initializer_list>
#include <optional>
#include "GWRBase.h"
#include "RegressionDiagnostic.h"
#include "IBandwidthSelectable.h"
#include "IVarialbeSelectable.h"
#include "IParallelizable.h"

namespace gwm
{

class GWRBasic : public GWRBase, public IBandwidthSelectable, public IVarialbeSelectable, public IParallelizable, public IParallelOpenmpEnabled, public IParallelCudaEnabled, public IParallelMpiEnabled
{
public:

    enum BandwidthSelectionCriterionType
    {
        AIC,
        CV
    };

    static std::unordered_map<BandwidthSelectionCriterionType, std::string> BandwidthSelectionCriterionTypeNameMapper;

    typedef arma::mat (GWRBasic::*PredictCalculator)(const arma::mat&, const arma::mat&, const arma::vec&);
    typedef arma::mat (GWRBasic::*FitCalculator)();
    typedef arma::mat (GWRBasic::*FitCoreCalculator)(const arma::mat&, const arma::vec&, const SpatialWeight&);
    typedef arma::mat (GWRBasic::*FitCoreSHatCalculator)(const arma::mat&, const arma::vec&, const SpatialWeight&, arma::vec&);
    typedef arma::mat (GWRBasic::*FitCoreCVCalculator)(const arma::mat&, const arma::vec&, const SpatialWeight&);

    typedef double (GWRBasic::*BandwidthSelectionCriterionCalculator)(BandwidthWeight*);
    typedef double (GWRBasic::*IndepVarsSelectCriterionCalculator)(const std::vector<std::size_t>&);

private:

    static RegressionDiagnostic CalcDiagnostic(const arma::mat& x, const arma::vec& y, const arma::mat& betas, const arma::vec& shat);

public:

    GWRBasic() {}

    GWRBasic(const arma::mat& x, const arma::vec& y, const arma::mat& coords, const SpatialWeight& spatialWeight, bool hasHatMatrix = true, bool hasIntercept = true)
        : GWRBase(x, y, spatialWeight, coords)
    {
        mHasHatMatrix = hasHatMatrix;
        mHasIntercept = hasIntercept;
    }

    ~GWRBasic() {}

public:

    bool isAutoselectBandwidth() const { return mIsAutoselectBandwidth; }

    void setIsAutoselectBandwidth(bool isAutoSelect) { mIsAutoselectBandwidth = isAutoSelect; }

    BandwidthSelectionCriterionType bandwidthSelectionCriterion() const { return mBandwidthSelectionCriterion; }

    void setBandwidthSelectionCriterion(const BandwidthSelectionCriterionType& criterion);

    void setGoldenUpperBounds(double value) { mGoldenUpperBounds = value; }

    void setGoldenLowerBounds(double value) { mGoldenLowerBounds = value; }

    bool isAutoselectIndepVars() const { return mIsAutoselectIndepVars; }

    void setIsAutoselectIndepVars(bool isAutoSelect) { mIsAutoselectIndepVars = isAutoSelect; }

    double indepVarSelectionThreshold() const { return mIndepVarSelectionThreshold; }

    void setIndepVarSelectionThreshold(double threshold) { mIndepVarSelectionThreshold = threshold; }

    const VariablesCriterionList& indepVarsSelectionCriterionList() const { return mIndepVarsSelectionCriterionList; }

    const BandwidthCriterionList& bandwidthSelectionCriterionList() const { return mBandwidthSelectionCriterionList; }

    bool hasHatMatrix() const { return mHasHatMatrix; }

    void setHasHatMatrix(const bool has) { mHasHatMatrix = has; }

    const arma::mat& betasSE() { return mBetasSE; }

    const arma::vec& sHat() { return mSHat; }

    const arma::vec& qDiag() { return mQDiag; }

    const arma::mat& s() { return mS; }

    const arma::cube& c() { return mC; }

    bool isStoreS() { return mStoreS ? true : (mHasHatMatrix && (mCoords.n_rows < 8192)); }

    bool isStoreC() { return mStoreC; }

    void setStoreS(bool flag) { mStoreS = flag; }

    void setStoreC(bool flag) { mStoreC = flag; }

public:     // Implement Algorithm
    bool isValid() override;

public:     // Implement IRegressionAnalysis
    arma::mat predict(const arma::mat& locations) override;

    arma::mat fit() override;

public:     // Implement IVariableSelectable
    Status getCriterion(const std::vector<size_t>& variables, double& criterion) override
    {
        criterion = (this->*mIndepVarsSelectionCriterionFunction)(variables);
        return mStatus;
    }

    std::vector<std::size_t> selectedVariables() override
    {
        return mSelectedIndepVars;
    }

    double indepVarsSelectionCriterion(const std::vector<std::size_t>& indepVars);


public:     // Implement IBandwidthSelectable
    Status getCriterion(BandwidthWeight* weight, double& criterion) override
    {
        criterion = (this->*mBandwidthSelectionCriterionFunction)(weight);
        return mStatus;
    }

    double bandwidthSizeCriterionCV(BandwidthWeight* bandwidthWeight);

    double bandwidthSizeCriterionAIC(BandwidthWeight* bandwidthWeight);


private:

    arma::mat predictSerial(const arma::mat& locations, const arma::mat& x, const arma::vec& y);

    arma::mat fitBase();


private:

    arma::mat fitCoreSerial(const arma::mat& x, const arma::vec& y, const SpatialWeight& sw);

    arma::mat fitCoreSHatSerial(const arma::mat& x, const arma::vec& y, const SpatialWeight& sw, arma::vec& shat);

    arma::mat fitCoreCVSerial(const arma::mat& x, const arma::vec& y, const SpatialWeight& sw);

#ifdef ENABLE_OPENMP

    arma::mat predictOmp(const arma::mat& locations, const arma::mat& x, const arma::vec& y);

    arma::mat fitCoreOmp(const arma::mat& x, const arma::vec& y, const SpatialWeight& sw);

    arma::mat fitCoreCVOmp(const arma::mat& x, const arma::vec& y, const SpatialWeight& sw);

    arma::mat fitCoreSHatOmp(const arma::mat& x, const arma::vec& y, const SpatialWeight& sw, arma::vec& shat);

#endif

#ifdef ENABLE_CUDA

    arma::mat fitCoreCuda(const arma::mat& x, const arma::vec& y, const SpatialWeight& sw);

    arma::mat predictCuda(const arma::mat& locations, const arma::mat& x, const arma::vec& y);

    arma::mat fitCoreCVCuda(const arma::mat& x, const arma::vec& y, const SpatialWeight& sw);

    arma::mat fitCoreSHatCuda(const arma::mat& x, const arma::vec& y, const SpatialWeight& sw, arma::vec& shat);

#endif

#ifdef ENABLE_MPI
    double indepVarsSelectionCriterionMpi(const std::vector<std::size_t>& indepVars);
    double bandwidthSizeCriterionCVMpi(BandwidthWeight* bandwidthWeight);
    double bandwidthSizeCriterionAICMpi(BandwidthWeight* bandwidthWeight);
    arma::mat fitMpi();
#endif // ENABLE_MPI

public:     // Implement IParallelizable
    int parallelAbility() const override
    {
        return ParallelType::SerialOnly
#ifdef ENABLE_OPENMP
            | ParallelType::OpenMP
#endif // ENABLE_OPENMP
#ifdef ENABLE_CUDA
            | ParallelType::CUDA
#endif // ENABLE_CUDA
#ifdef ENABLE_MPI
#ifdef ENABLE_OPENMP
            | ParallelType::OpenMP
#endif // ENABLE_OPENMP
#ifdef ENABLE_CUDA
            | ParallelType::CUDA
#endif // ENABLE_CUDA
#endif // ENABLE_MPI
        ;
    }

    ParallelType parallelType() const override { return mParallelType; }

    void setParallelType(const ParallelType& type) override;

public:     // Implement IGwmParallelOpenmpEnabled
    void setOmpThreadNum(const int threadNum) override { mOmpThreadNum = threadNum; }
    void setGPUId(const int gpuId) override { mGpuId = gpuId; };
    void setGroupSize(const std::size_t size) override { mGroupLength = size; };
    int workerId() override { return mWorkerId; }
    void setWorkerId(int id) override { mWorkerId = id; };
    void setWorkerNum(int size) override { mWorkerNum = size; };

protected:

    void createPredictionDistanceParameter(const arma::mat& locations);

protected:
    bool mHasHatMatrix = true;
    bool mHasFTest = false;
    bool mHasPredict = false;

    bool mIsAutoselectIndepVars = false;
    double mIndepVarSelectionThreshold = 3.0;
    IndepVarsSelectCriterionCalculator mIndepVarsSelectionCriterionFunction = &GWRBasic::indepVarsSelectionCriterion;
    VariablesCriterionList mIndepVarsSelectionCriterionList;
    std::vector<std::size_t> mSelectedIndepVars;
    std::size_t mIndepVarSelectionProgressTotal = 0;
    std::size_t mIndepVarSelectionProgressCurrent = 0;

    bool mIsAutoselectBandwidth = false;
    BandwidthSelectionCriterionType mBandwidthSelectionCriterion = BandwidthSelectionCriterionType::AIC;
    BandwidthSelectionCriterionCalculator mBandwidthSelectionCriterionFunction = &GWRBasic::bandwidthSizeCriterionCV;
    BandwidthCriterionList mBandwidthSelectionCriterionList;
    double mBandwidthLastCriterion = DBL_MAX;
    std::optional<double> mGoldenUpperBounds;
    std::optional<double> mGoldenLowerBounds;

    PredictCalculator mPredictFunction = &GWRBasic::predictSerial;
    FitCalculator mFitFunction = &GWRBasic::fitBase;
    FitCoreCalculator mFitCoreFunction = &GWRBasic::fitCoreSerial;
    FitCoreSHatCalculator mFitCoreSHatFunction = &GWRBasic::fitCoreSHatSerial;
    FitCoreCVCalculator mFitCoreCVFunction = &GWRBasic::fitCoreCVSerial;

    ParallelType mParallelType = ParallelType::SerialOnly;
    int mOmpThreadNum = 8;
    size_t mGroupLength = 64;
    int mGpuId = 0;
    int mWorkerId = 0;
    int mWorkerNum = 1;
    arma::uword mWorkRangeSize = 0;
    std::optional<std::pair<arma::uword, arma::uword>> mWorkRange;

    arma::mat mBetasSE;
    arma::vec mSHat;
    arma::vec mQDiag;
    arma::mat mS;
    arma::cube mC;
    bool mStoreS = false;
    bool mStoreC = false;
};

}

#endif  // GWRBASIC_H