diff --git a/include/evalhyd/detail/uncertainty.hpp b/include/evalhyd/detail/uncertainty.hpp index a0adf29e29fb966d58e85993e98b3943f7a3db44..de7d746621195ebb48f6439fed377b4003ce1173 100644 --- a/include/evalhyd/detail/uncertainty.hpp +++ b/include/evalhyd/detail/uncertainty.hpp @@ -30,7 +30,7 @@ namespace evalhyd { inline auto bootstrap( const std::vector<std::string>& datetimes, - int n_samples, int len_sample + int n_samples, int len_sample, long int seed ) { // convert string to time_point (via tm) @@ -120,6 +120,7 @@ namespace evalhyd } // generate bootstrapping experiment + xt::random::seed(seed); xt::xtensor<int, 2> experiment = xt::random::randint( {n_samples, len_sample}, start_yr, end_yr ); diff --git a/include/evalhyd/detail/utils.hpp b/include/evalhyd/detail/utils.hpp index 620f5b3b9aaf7f030e7f51d6b98424807bd33100..839b49d53f7ccfafb17e8d29f0b8bdc156f1cf9d 100644 --- a/include/evalhyd/detail/utils.hpp +++ b/include/evalhyd/detail/utils.hpp @@ -95,14 +95,23 @@ namespace evalhyd "invalid value for bootstrap summary" ); } - // set seed - if (bootstrap.find("seed") == bootstrap.end()) + } + + // Function to get a seed for random generators + // + // \param seed + // Optional value to use to set the seed for random generators. + // \return + // A seed value to use in random generators. + inline long int get_seed(xtl::xoptional<int, bool> seed) + { + if (seed.has_value()) { - xt::random::seed(time(nullptr)); + return seed.value(); } else { - xt::random::seed(bootstrap.find("seed")->second); + return std::time(nullptr); } } } diff --git a/include/evalhyd/evald.hpp b/include/evalhyd/evald.hpp index 31bc5440410e44783d7af37c80795a2549f14866..a9f250b7f2f113bfb752ccf2049e599257b7d854 100644 --- a/include/evalhyd/evald.hpp +++ b/include/evalhyd/evald.hpp @@ -99,12 +99,11 @@ namespace evalhyd /// bootstrap: ``std::unordered_map<std::string, int>``, optional /// Parameters for the bootstrapping method used to estimate the /// sampling uncertainty in the evaluation of the predictions. - /// Three parameters are mandatory ('n_samples' the number of random - /// samples, 'len_sample' the length of one sample in number of years, + /// The parameters are: 'n_samples' the number of random samples, + /// 'len_sample' the length of one sample in number of years, /// and 'summary' the statistics to return to characterise the - /// sampling distribution), and one parameter is optional ('seed'). - /// If not provided, no bootstrapping is performed. If provided, - /// *dts* must also be provided. + /// sampling distribution). If not provided, no bootstrapping is + /// performed. If provided, *dts* must also be provided. /// /// .. seealso:: :doc:`../../functionalities/bootstrapping` /// @@ -116,6 +115,10 @@ namespace evalhyd /// 21st of May 2007 at 4 in the afternoon is "2007-05-21 16:00:00"). /// If provided, it is only used if *bootstrap* is also provided. /// + /// seed: ``int``, optional + /// A value for the seed used by random generators. This parameter + /// guarantees the reproducibility of the metric values between calls. + /// /// :Returns: /// /// ``std::vector<xt::xarray<double>>`` @@ -171,7 +174,9 @@ namespace evalhyd const xt::xtensor<std::array<char, 32>, 1>& m_cdt = {}, xtl::xoptional<const std::unordered_map<std::string, int>, bool> bootstrap = xtl::missing<const std::unordered_map<std::string, int>>(), - const std::vector<std::string>& dts = {} + const std::vector<std::string>& dts = {}, + xtl::xoptional<const int, bool> seed = + xtl::missing<const int>() ) { // check ranks of tensors @@ -206,6 +211,9 @@ namespace evalhyd utils::check_bootstrap(bootstrap.value()); } + // get a seed for random generators + auto random_seed = utils::get_seed(seed); + // check that data dimensions are compatible // > time if (q_obs_.shape(1) != q_prd_.shape(1)) @@ -384,7 +392,7 @@ namespace evalhyd } exp = uncertainty::bootstrap( - dts, n_samples, len_sample + dts, n_samples, len_sample, random_seed ); } else diff --git a/include/evalhyd/evalp.hpp b/include/evalhyd/evalp.hpp index 1686ed609b22ef57f289f7563a526d6adb1e048e..4bd0f955d5afafa24742e81d9dbb85bc209705f8 100644 --- a/include/evalhyd/evalp.hpp +++ b/include/evalhyd/evalp.hpp @@ -100,12 +100,11 @@ namespace evalhyd /// bootstrap: ``std::unordered_map<std::string, int>``, optional /// Parameters for the bootstrapping method used to estimate the /// sampling uncertainty in the evaluation of the predictions. - /// Three parameters are mandatory ('n_samples' the number of random - /// samples, 'len_sample' the length of one sample in number of years, + /// The parameters are: 'n_samples' the number of random samples, + /// 'len_sample' the length of one sample in number of years, /// and 'summary' the statistics to return to characterise the - /// sampling distribution), and one parameter is optional ('seed'). - /// If not provided, no bootstrapping is performed. If provided, - /// *dts* must also be provided. + /// sampling distribution). If not provided, no bootstrapping is + /// performed. If provided, *dts* must also be provided. /// /// .. seealso:: :doc:`../../functionalities/bootstrapping` /// @@ -117,6 +116,10 @@ namespace evalhyd /// 21st of May 2007 at 4 in the afternoon is "2007-05-21 16:00:00"). /// If provided, it is only used if *bootstrap* is also provided. /// + /// seed: ``int``, optional + /// A value for the seed used by random generators. This parameter + /// guarantees the reproducibility of the metric values between calls. + /// /// :Returns: /// /// ``std::vector<xt::xarray<double>>`` @@ -163,7 +166,9 @@ namespace evalhyd const xt::xtensor<std::array<char, 32>, 2>& m_cdt = {}, xtl::xoptional<const std::unordered_map<std::string, int>, bool> bootstrap = xtl::missing<const std::unordered_map<std::string, int>>(), - const std::vector<std::string>& dts = {} + const std::vector<std::string>& dts = {}, + xtl::xoptional<const int, bool> seed = + xtl::missing<const int>() ) { // check ranks of tensors @@ -208,6 +213,9 @@ namespace evalhyd utils::check_bootstrap(bootstrap.value()); } + // get a seed for random generators + auto random_seed = utils::get_seed(seed); + // check that data dimensions are compatible // > time if (q_obs_.shape(1) != q_prd_.shape(3)) @@ -348,7 +356,9 @@ namespace evalhyd ); } - b_exp = uncertainty::bootstrap(dts, n_samples, len_sample); + b_exp = uncertainty::bootstrap( + dts, n_samples, len_sample, random_seed + ); } else { diff --git a/tests/test_uncertainty.cpp b/tests/test_uncertainty.cpp index 50c32f79b1cc7ac85eabac1dba77dd81f2a83e9d..5889ad36f912baba0cfb409d09a54a25d6dcd7e7 100644 --- a/tests/test_uncertainty.cpp +++ b/tests/test_uncertainty.cpp @@ -19,12 +19,9 @@ TEST(UncertaintyTests, TestBootstrapGenerator) "2013-10-01 00:00:00", "2013-10-02 00:00:00", "2013-10-03 00:00:00", "2013-10-04 00:00:00", "2013-10-05 00:00:00", "2013-10-06 00:00:00", "2013-10-07 00:00:00", "2013-10-08 00:00:00", "2013-10-09 00:00:00", "2013-10-10 00:00:00", "2013-10-11 00:00:00", "2013-10-12 00:00:00", "2013-10-13 00:00:00", "2013-10-14 00:00:00", "2013-10-15 00:00:00", "2013-10-16 00:00:00", "2013-10-17 00:00:00", "2013-10-18 00:00:00", "2013-10-19 00:00:00", "2013-10-20 00:00:00", "2013-10-21 00:00:00", "2013-10-22 00:00:00", "2013-10-23 00:00:00", "2013-10-24 00:00:00", "2013-10-25 00:00:00", "2013-10-26 00:00:00", "2013-10-27 00:00:00", "2013-10-28 00:00:00", "2013-10-29 00:00:00", "2013-10-30 00:00:00", "2013-10-31 00:00:00", "2013-11-01 00:00:00", "2013-11-02 00:00:00", "2013-11-03 00:00:00", "2013-11-04 00:00:00", "2013-11-05 00:00:00", "2013-11-06 00:00:00", "2013-11-07 00:00:00", "2013-11-08 00:00:00", "2013-11-09 00:00:00", "2013-11-10 00:00:00", "2013-11-11 00:00:00", "2013-11-12 00:00:00", "2013-11-13 00:00:00", "2013-11-14 00:00:00", "2013-11-15 00:00:00", "2013-11-16 00:00:00", "2013-11-17 00:00:00", "2013-11-18 00:00:00", "2013-11-19 00:00:00", "2013-11-20 00:00:00", "2013-11-21 00:00:00", "2013-11-22 00:00:00", "2013-11-23 00:00:00", "2013-11-24 00:00:00", "2013-11-25 00:00:00", "2013-11-26 00:00:00", "2013-11-27 00:00:00", "2013-11-28 00:00:00", "2013-11-29 00:00:00", "2013-11-30 00:00:00", "2013-12-01 00:00:00", "2013-12-02 00:00:00", "2013-12-03 00:00:00", "2013-12-04 00:00:00", "2013-12-05 00:00:00", "2013-12-06 00:00:00", "2013-12-07 00:00:00", "2013-12-08 00:00:00", "2013-12-09 00:00:00", "2013-12-10 00:00:00", "2013-12-11 00:00:00", "2013-12-12 00:00:00", "2013-12-13 00:00:00", "2013-12-14 00:00:00", "2013-12-15 00:00:00", "2013-12-16 00:00:00", "2013-12-17 00:00:00", "2013-12-18 00:00:00", "2013-12-19 00:00:00", "2013-12-20 00:00:00", "2013-12-21 00:00:00", "2013-12-22 00:00:00", "2013-12-23 00:00:00", "2013-12-24 00:00:00", "2013-12-25 00:00:00", "2013-12-26 00:00:00", "2013-12-27 00:00:00", "2013-12-28 00:00:00", "2013-12-29 00:00:00", "2013-12-30 00:00:00", "2013-12-31 00:00:00", "2014-01-01 00:00:00", "2014-01-02 00:00:00", "2014-01-03 00:00:00", "2014-01-04 00:00:00", "2014-01-05 00:00:00", "2014-01-06 00:00:00", "2014-01-07 00:00:00", "2014-01-08 00:00:00", "2014-01-09 00:00:00", "2014-01-10 00:00:00", "2014-01-11 00:00:00", "2014-01-12 00:00:00", "2014-01-13 00:00:00", "2014-01-14 00:00:00", "2014-01-15 00:00:00", "2014-01-16 00:00:00", "2014-01-17 00:00:00", "2014-01-18 00:00:00", "2014-01-19 00:00:00", "2014-01-20 00:00:00", "2014-01-21 00:00:00", "2014-01-22 00:00:00", "2014-01-23 00:00:00", "2014-01-24 00:00:00", "2014-01-25 00:00:00", "2014-01-26 00:00:00", "2014-01-27 00:00:00", "2014-01-28 00:00:00", "2014-01-29 00:00:00", "2014-01-30 00:00:00", "2014-01-31 00:00:00", "2014-02-01 00:00:00", "2014-02-02 00:00:00", "2014-02-03 00:00:00", "2014-02-04 00:00:00", "2014-02-05 00:00:00", "2014-02-06 00:00:00", "2014-02-07 00:00:00", "2014-02-08 00:00:00", "2014-02-09 00:00:00", "2014-02-10 00:00:00", "2014-02-11 00:00:00", "2014-02-12 00:00:00", "2014-02-13 00:00:00", "2014-02-14 00:00:00", "2014-02-15 00:00:00", "2014-02-16 00:00:00", "2014-02-17 00:00:00", "2014-02-18 00:00:00", "2014-02-19 00:00:00", "2014-02-20 00:00:00", "2014-02-21 00:00:00", "2014-02-22 00:00:00", "2014-02-23 00:00:00", "2014-02-24 00:00:00", "2014-02-25 00:00:00", "2014-02-26 00:00:00", "2014-02-27 00:00:00", "2014-02-28 00:00:00", "2014-03-01 00:00:00", "2014-03-02 00:00:00", "2014-03-03 00:00:00", "2014-03-04 00:00:00", "2014-03-05 00:00:00", "2014-03-06 00:00:00", "2014-03-07 00:00:00", "2014-03-08 00:00:00", "2014-03-09 00:00:00", "2014-03-10 00:00:00", "2014-03-11 00:00:00", "2014-03-12 00:00:00", "2014-03-13 00:00:00", "2014-03-14 00:00:00", "2014-03-15 00:00:00", "2014-03-16 00:00:00", "2014-03-17 00:00:00", "2014-03-18 00:00:00", "2014-03-19 00:00:00", "2014-03-20 00:00:00", "2014-03-21 00:00:00", "2014-03-22 00:00:00", "2014-03-23 00:00:00", "2014-03-24 00:00:00", "2014-03-25 00:00:00", "2014-03-26 00:00:00", "2014-03-27 00:00:00", "2014-03-28 00:00:00", "2014-03-29 00:00:00", "2014-03-30 00:00:00", "2014-03-31 00:00:00", "2014-04-01 00:00:00", "2014-04-02 00:00:00", "2014-04-03 00:00:00", "2014-04-04 00:00:00", "2014-04-05 00:00:00", "2014-04-06 00:00:00", "2014-04-07 00:00:00", "2014-04-08 00:00:00", "2014-04-09 00:00:00", "2014-04-10 00:00:00", "2014-04-11 00:00:00", "2014-04-12 00:00:00", "2014-04-13 00:00:00", "2014-04-14 00:00:00", "2014-04-15 00:00:00", "2014-04-16 00:00:00", "2014-04-17 00:00:00", "2014-04-18 00:00:00", "2014-04-19 00:00:00", "2014-04-20 00:00:00", "2014-04-21 00:00:00", "2014-04-22 00:00:00", "2014-04-23 00:00:00", "2014-04-24 00:00:00", "2014-04-25 00:00:00", "2014-04-26 00:00:00", "2014-04-27 00:00:00", "2014-04-28 00:00:00", "2014-04-29 00:00:00", "2014-04-30 00:00:00", "2014-05-01 00:00:00", "2014-05-02 00:00:00", "2014-05-03 00:00:00", "2014-05-04 00:00:00", "2014-05-05 00:00:00", "2014-05-06 00:00:00", "2014-05-07 00:00:00", "2014-05-08 00:00:00", "2014-05-09 00:00:00", "2014-05-10 00:00:00", "2014-05-11 00:00:00", "2014-05-12 00:00:00", "2014-05-13 00:00:00", "2014-05-14 00:00:00", "2014-05-15 00:00:00", "2014-05-16 00:00:00", "2014-05-17 00:00:00", "2014-05-18 00:00:00", "2014-05-19 00:00:00", "2014-05-20 00:00:00", "2014-05-21 00:00:00", "2014-05-22 00:00:00", "2014-05-23 00:00:00", "2014-05-24 00:00:00", "2014-05-25 00:00:00", "2014-05-26 00:00:00", "2014-05-27 00:00:00", "2014-05-28 00:00:00", "2014-05-29 00:00:00", "2014-05-30 00:00:00", "2014-05-31 00:00:00", "2014-06-01 00:00:00", "2014-06-02 00:00:00", "2014-06-03 00:00:00", "2014-06-04 00:00:00", "2014-06-05 00:00:00", "2014-06-06 00:00:00", "2014-06-07 00:00:00", "2014-06-08 00:00:00", "2014-06-09 00:00:00", "2014-06-10 00:00:00", "2014-06-11 00:00:00", "2014-06-12 00:00:00", "2014-06-13 00:00:00", "2014-06-14 00:00:00", "2014-06-15 00:00:00", "2014-06-16 00:00:00", "2014-06-17 00:00:00", "2014-06-18 00:00:00", "2014-06-19 00:00:00", "2014-06-20 00:00:00", "2014-06-21 00:00:00", "2014-06-22 00:00:00", "2014-06-23 00:00:00", "2014-06-24 00:00:00", "2014-06-25 00:00:00", "2014-06-26 00:00:00", "2014-06-27 00:00:00", "2014-06-28 00:00:00", "2014-06-29 00:00:00", "2014-06-30 00:00:00", "2014-07-01 00:00:00", "2014-07-02 00:00:00", "2014-07-03 00:00:00", "2014-07-04 00:00:00", "2014-07-05 00:00:00", "2014-07-06 00:00:00", "2014-07-07 00:00:00", "2014-07-08 00:00:00", "2014-07-09 00:00:00", "2014-07-10 00:00:00", "2014-07-11 00:00:00", "2014-07-12 00:00:00", "2014-07-13 00:00:00", "2014-07-14 00:00:00", "2014-07-15 00:00:00", "2014-07-16 00:00:00", "2014-07-17 00:00:00", "2014-07-18 00:00:00", "2014-07-19 00:00:00", "2014-07-20 00:00:00", "2014-07-21 00:00:00", "2014-07-22 00:00:00", "2014-07-23 00:00:00", "2014-07-24 00:00:00", "2014-07-25 00:00:00", "2014-07-26 00:00:00", "2014-07-27 00:00:00", "2014-07-28 00:00:00", "2014-07-29 00:00:00", "2014-07-30 00:00:00", "2014-07-31 00:00:00", "2014-08-01 00:00:00", "2014-08-02 00:00:00", "2014-08-03 00:00:00", "2014-08-04 00:00:00", "2014-08-05 00:00:00", "2014-08-06 00:00:00", "2014-08-07 00:00:00", "2014-08-08 00:00:00", "2014-08-09 00:00:00", "2014-08-10 00:00:00", "2014-08-11 00:00:00", "2014-08-12 00:00:00", "2014-08-13 00:00:00", "2014-08-14 00:00:00", "2014-08-15 00:00:00", "2014-08-16 00:00:00", "2014-08-17 00:00:00", "2014-08-18 00:00:00", "2014-08-19 00:00:00", "2014-08-20 00:00:00", "2014-08-21 00:00:00", "2014-08-22 00:00:00", "2014-08-23 00:00:00", "2014-08-24 00:00:00", "2014-08-25 00:00:00", "2014-08-26 00:00:00", "2014-08-27 00:00:00", "2014-08-28 00:00:00", "2014-08-29 00:00:00", "2014-08-30 00:00:00", "2014-08-31 00:00:00", "2014-09-01 00:00:00", "2014-09-02 00:00:00", "2014-09-03 00:00:00", "2014-09-04 00:00:00", "2014-09-05 00:00:00", "2014-09-06 00:00:00", "2014-09-07 00:00:00", "2014-09-08 00:00:00", "2014-09-09 00:00:00", "2014-09-10 00:00:00", "2014-09-11 00:00:00", "2014-09-12 00:00:00", "2014-09-13 00:00:00", "2014-09-14 00:00:00", "2014-09-15 00:00:00", "2014-09-16 00:00:00", "2014-09-17 00:00:00", "2014-09-18 00:00:00", "2014-09-19 00:00:00", "2014-09-20 00:00:00", "2014-09-21 00:00:00", "2014-09-22 00:00:00", "2014-09-23 00:00:00", "2014-09-24 00:00:00", "2014-09-25 00:00:00", "2014-09-26 00:00:00", "2014-09-27 00:00:00", "2014-09-28 00:00:00", "2014-09-29 00:00:00", "2014-09-30 00:00:00" }; - // fix seed to know which experiment is going to be generated - xt::random::seed(7); - // use bootstrap generator to get samples - // experiment (5 samples of 4 year length): - auto samples = evalhyd::uncertainty::bootstrap(datetimes, 5, 4); + // experiment (5 samples of 4 year length, set seed to fixed value 7): + auto samples = evalhyd::uncertainty::bootstrap(datetimes, 5, 4, 7); // manually generate results expected from random generator std::vector<std::vector<int>> results;