Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@
*.RData
*.o
*.so
*.Identifier
test/fdapde_test
test/.cache
test/build/
test/CMakeFiles/
test/_deps/
test/libs/
test/lib/
./run_tests.sh

4 changes: 3 additions & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
[submodule "fdaPDE/core"]
path = fdaPDE/core
url = https://github.com/fdaPDE/fdaPDE-core
url = https://github.com/RiccardoSena/fdaPDE-core.git
branch = stable
[submodule "/home/jellyfish/fdaPDE-cpp/fdaPDE/core"]
url = https://github.com/RiccardoSena/fdaPDE-core.git
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,33 @@ It is built on top of the [fdaPDE Core Library](https://github.com/fdaPDE/fdaPDE

## Documentation
Documentation can be found on our [documentation site](https://fdapde.github.io/)

## Installation
The source code of this project can be found at [https://github.com/RiccardoSena/fdaPDE-cpp.git](https://github.com/RiccardoSena/fdaPDE-cpp.git), which is a fork of the fdaPDE repository. The prerequisites to install and run test cases are:

- A C++17 compliant compiler
- Make
- CMake
- The **Eigen** library (at least version 3.3)

### Instructions to install the library:

1. Clone the repository:
```bash
git clone https://github.com/RiccardoSena/fdaPDE-cpp.git
2. Then, navigate into the develop branch and update the core submodule:
```bash
cd fdaPDE-cpp
git submodule init
git submodule update
3. To run the test cases, use the following commands inside the fdaPDE-cpp directory:
```bash
cd test
mkdir build
cd build
cmake ..
make
cd ..
./run_tests.sh
It should be noted that in the test/main.cpp file, one can choose to run all tests about different models and methods. The ones that are compliant to our development are test/src/inference_test.cpp and test/src/inferencetime_test.cpp

29 changes: 17 additions & 12 deletions fdaPDE/calibration/calibration_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,23 @@ namespace calibration {

template <typename Calibrator, typename... Args_> class ConfiguredCalibrator {
private:
using CalibratorType = std::decay_t<Calibrator>;
using CalibratorType = std::remove_const_t<Calibrator>;
using ArgsPackType = std::tuple<std::decay_t<Args_>...>;
CalibratorType c_;
ArgsPackType args_; // parameter pack forwarded to calibration strategy at fit time
template <typename ModelType_, std::size_t... I>
auto call_(ModelType_& model, [[maybe_unused]] std::index_sequence<I...> seq) {
return c_.fit(model, std::get<I>(args_)...); // forward stored parameters to calibrator
}

// templated member detection trait for set_model()
template <typename T, typename M, typename = void> struct callback_require_model : std::false_type { };
template <typename T, typename M>
struct callback_require_model<
T, M, std::void_t<decltype(std::declval<T>().template set_model<M>(std::declval<M>()))>> : std::true_type { };
T, M, std::void_t<decltype(std::declval<T>().template set_model<M>(std::declval<M>()))>
> : std::true_type { };
public:
ConfiguredCalibrator() = default;
ConfiguredCalibrator(const CalibratorType& c, Args_&&... args) :
c_(c), args_(std::make_tuple(std::forward<Args_>(args)...)) {};
ConfiguredCalibrator(CalibratorType c, Args_&&... args) :
c_(c), args_(std::make_tuple(std::forward<Args_>(args)...)) { }
template <typename ModelType_> DVector<double> fit(ModelType_&& model) {
// forward model instance to callbacks which require it
auto set_model = [&model](auto&& arg) {
Expand All @@ -56,18 +55,24 @@ template <typename Calibrator, typename... Args_> class ConfiguredCalibrator {
};

template <typename T> struct CalibratorBase {
template <typename... Args> ConfiguredCalibrator<T, Args...> operator()(Args&&... args) const {
return ConfiguredCalibrator<T, Args...>(static_cast<const T&>(*this), std::forward<Args>(args)...);
template <typename... Args>
ConfiguredCalibrator<std::add_lvalue_reference_t<T>, Args...> operator()(Args&&... args) & {
return ConfiguredCalibrator<std::add_lvalue_reference_t<T>, Args...>(
static_cast<std::add_lvalue_reference_t<T>>(*this), std::forward<Args>(args)...);
}
// rvalue ref-qualified overload pushes calibrator by copy
template <typename... Args> ConfiguredCalibrator<T, Args...> operator()(Args&&... args) && {
return {static_cast<T&>(*this), std::forward<Args>(args)...};
}
};

// a type-erasure wrapper for a (configured) calibration algorithm for models of type ModelType
template <typename ModelType_> struct Calibrator__ {
template <typename T> using fn_ptrs = fdapde::mem_fn_ptrs<&T::template fit<ModelType_>, &T::optimum>;
decltype(auto) fit(ModelType_& model) { return fdapde::invoke<DVector<double>, 0>(*this, model); }
decltype(auto) optimum(ModelType_& model) { return fdapde::invoke<DVector<double>, 1>(*this, model); }
template <typename T> using fn_ptrs = mem_fn_ptrs<&T::template fit<ModelType_>, &T::optimum>;
decltype(auto) fit(ModelType_& model) { return invoke<DVector<double>, 0>(*this, model); }
decltype(auto) optimum() { return invoke<DVector<double>, 1>(*this); }
};
template <typename ModelType_> using Calibrator = fdapde::erase<fdapde::heap_storage, Calibrator__<ModelType_>>;
template <typename ModelType_> using Calibrator = erase<heap_storage, Calibrator__<ModelType_>>;

} // namespace calibration
} // namespace fdapde
Expand Down
18 changes: 10 additions & 8 deletions fdaPDE/calibration/gcv.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,31 +34,33 @@ template <typename RegularizationType> class GCV : public CalibratorBase<GCV<Reg
};
public:
// constructor
GCV() = default;
template <typename Optimizer_, typename EDFStrategy_> GCV(Optimizer_&& opt, EDFStrategy_&& edf) : opt_(opt) {
GCV() {
if constexpr (!is_void<RegularizationType>::value) {
if constexpr (std::is_same_v<RegularizationType, models::SpaceOnly>) {
gcv_.resize(1);
} else { // space-time models
gcv_.resize(2);
}
constexpr int n_lambda = std::is_same_v<RegularizationType, models::SpaceOnly> ? 1 : 2;
gcv_.resize(n_lambda);
}
}
template <typename Optimizer_, typename EDFStrategy_> GCV(Optimizer_&& opt, EDFStrategy_&& edf) : GCV() {
opt_ = opt;
gcv_.set_edf_strategy(edf);
}
// selects best smoothing parameter of regression model by minimization of GCV index
template <typename ModelType_, typename... Args> DVector<double> fit(ModelType_& model, Args&&... args) {
fdapde_assert(gcv_.inner_size() != 0);
fdapde_assert(gcv_.inner_size() != 0 && bool(opt_) == true);
gcv_.set_model(model);
return opt_.optimize(gcv_, std::forward<Args>(args)...);
}
DVector<double> optimum() { return opt_.optimum(); } // optimal \lambda found
const std::vector<double>& edfs() const { return gcv_.edfs(); } // equivalent degrees of freedom q + Tr[S]
const std::vector<double>& gcvs() const { return gcv_.gcvs(); } // computed values of GCV index
// setters
void set_step(double step) { gcv_.set_step(step); }
template <typename Optimizer_> void set_optimizer(Optimizer_&& opt) { opt_ = opt; }
template <typename RegularizationType_> void set() { // set GCV's domain dimension
fdapde_static_assert(is_void<RegularizationType>::value, THIS_METHOD_IS_FOR_VOID_REGULARIZATION_ONLY);
gcv_.resize(models::n_smoothing_parameters<RegularizationType_>::value);
}
template <typename EDFStrategy_> void set_edf_strategy(EDFStrategy_&& edf) { gcv_.set_edf_strategy(edf); }
};
// template argument deduction rule
template <typename Optimizer_, typename EDFStrategy_> GCV(Optimizer_&& opt, EDFStrategy_&& edf) -> GCV<void>;
Expand Down
17 changes: 9 additions & 8 deletions fdaPDE/calibration/kfold_cv.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,24 +71,25 @@ class KCV : public CalibratorBase<KCV> {

// selects best smoothing parameter of model according to a K-fold cross validation strategy
template <typename ModelType, typename ScoreType>
DVector<double> fit(ModelType& model, const std::vector<DVector<double>>& lambdas, ScoreType cv_score) {
DVector<double> fit(ModelType& model, const DMatrix<double>& lambdas, ScoreType cv_score) {
fdapde_assert(lambdas.cols() == 1 || lambdas.cols() == 2);
// reserve space for CV scores
scores_.resize(K_, lambdas.size());
scores_.resize(K_, lambdas.rows());
if (shuffle_) { // perform a first shuffling of the data if required
model.set_data(model.data().shuffle(seed_));
}
// cycle over all tuning parameters
for (std::size_t j = 0; j < lambdas.size(); ++j) {
for (int j = 0; j < lambdas.rows(); ++j) {
for (int fold = 0; fold < K_; ++fold) { // fixed a tuning parameter, cycle over all data splits
// compute train-test partition and evaluate CV score
TrainTestPartition partition_mask = split(model.data(), fold);
scores_.coeffRef(fold, j) = cv_score(lambdas[j], partition_mask.first, partition_mask.second);
scores_.coeffRef(fold, j) = cv_score(lambdas.row(j), partition_mask.first, partition_mask.second);
}
}
// reserve space for storing results
avg_scores_ = DVector<double>::Zero(lambdas.size());
std_scores_ = DVector<double>::Zero(lambdas.size());
for (std::size_t j = 0; j < lambdas.size(); ++j) {
avg_scores_ = DVector<double>::Zero(lambdas.rows());
std_scores_ = DVector<double>::Zero(lambdas.rows());
for (int j = 0; j < lambdas.rows(); ++j) {
// record the average score and its standard deviation computed among the K_ runs
double avg_score = 0;
for (int i = 0; i < K_; ++i) avg_score += scores_(i, j);
Expand All @@ -104,7 +105,7 @@ class KCV : public CalibratorBase<KCV> {
// store optimal lambda according to given metric F
Eigen::Index opt_score;
avg_scores_.minCoeff(&opt_score);
optimum_ = lambdas[opt_score];
optimum_ = lambdas.row(opt_score);
return optimum_;
}

Expand Down
2 changes: 1 addition & 1 deletion fdaPDE/calibration/rmse.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class RMSE {
RegressionView<void> model_;
public:
RMSE() = default;
template <typename ModelType> RMSE(const ModelType& model) : model_(model) {};
template <typename ModelType> RMSE(const ModelType& model) : model_(model) {}
template <typename ModelType> void set_model(const ModelType& model) { model_ = model; }

double operator()(
Expand Down
2 changes: 1 addition & 1 deletion fdaPDE/core
Submodule core updated 846 files
Loading