From 882193fb89d7b0993e6eb0a0eb35dae027168da7 Mon Sep 17 00:00:00 2001 From: Eduard Nicodei Date: Sun, 8 Mar 2015 13:31:28 +0000 Subject: [PATCH 1/4] Add "Sampling without replacement" function in jde. --- src/algorithm/jde.cpp | 39 +++++++++++++++++++++++++++++++++++++++ src/algorithm/jde.h | 1 + 2 files changed, 40 insertions(+) diff --git a/src/algorithm/jde.cpp b/src/algorithm/jde.cpp index 053c7c2a..21169120 100644 --- a/src/algorithm/jde.cpp +++ b/src/algorithm/jde.cpp @@ -581,6 +581,45 @@ std::string jde::human_readable_extra() const return s.str(); } +// Helper function. +/** + * Used to speed up evolve()'s way of selecting population members. + * Generate a random sample of 7 different elements, from {0..(NP - 1)} / {current_element}. + * + * @param[out] sample space holder for the selected elements + * @param[in] NP the "population size" + * @param[in] current_element this element will not be included in the final sample. + */ +void jde::generate_sample(std::vector &sample, const size_t NP, const size_t current_element) const +{ + std::vector elements; + size_t i; + + // Add elements in order. Skip current_element. + for (i = 0; i < NP; ++i) { + if (i == current_element) { + continue; + } + elements.push_back(i); + } + + // Shuffle elements. + for (i = 0; i < 7; ++i) { + // uniform_int<> rnd(a,b) gives values in the range [a,b] not [a,b). + // We have NP - 1 elements, therefore the range is [0, NP - i - 2]. + boost::uniform_int rnd_idx(0, NP - i - 2); + std::swap(elements[rnd_idx(m_urng)], elements[NP - i - 2]); + } + + // Create sample of the first 7 elements. + if (sample.size() > 0) { + sample.erase(sample.begin(), sample.end()); + } + for (i = 0; i < 7; ++i) { + sample.push_back(elements[i]); + } +} + }} //namespaces BOOST_CLASS_EXPORT_IMPLEMENT(pagmo::algorithm::jde) diff --git a/src/algorithm/jde.h b/src/algorithm/jde.h index d2fa0a08..e9cee135 100644 --- a/src/algorithm/jde.h +++ b/src/algorithm/jde.h @@ -68,6 +68,7 @@ class __PAGMO_VISIBLE jde : public base base_ptr clone() const; void evolve(population &) const; std::string get_name() const; + void generate_sample(std::vector &, const size_t, const size_t) const; protected: std::string human_readable_extra() const; From 063ea26ddbf332f7e5e65cbb8d03eff492da92f8 Mon Sep 17 00:00:00 2001 From: Eduard Nicodei Date: Sun, 8 Mar 2015 14:14:10 +0000 Subject: [PATCH 2/4] Bugfix: the selected (random) elements are at the end of the array. --- src/algorithm/jde.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algorithm/jde.cpp b/src/algorithm/jde.cpp index 21169120..a7a086e3 100644 --- a/src/algorithm/jde.cpp +++ b/src/algorithm/jde.cpp @@ -616,7 +616,7 @@ void jde::generate_sample(std::vector &sample, const size_t NP, const si sample.erase(sample.begin(), sample.end()); } for (i = 0; i < 7; ++i) { - sample.push_back(elements[i]); + sample.push_back(elements[elements.size() - i - 1]); } } From 2df4b8d29312951be4477aed117602bc135f0ca5 Mon Sep 17 00:00:00 2001 From: Eduard Nicodei Date: Sun, 8 Mar 2015 14:16:02 +0000 Subject: [PATCH 3/4] Use "Sampling Without Replacement" algorithm for small populations. --- src/algorithm/jde.cpp | 76 +++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 32 deletions(-) diff --git a/src/algorithm/jde.cpp b/src/algorithm/jde.cpp index a7a086e3..001238f7 100644 --- a/src/algorithm/jde.cpp +++ b/src/algorithm/jde.cpp @@ -189,38 +189,50 @@ void jde::evolve(population &pop) const //Start of the loop through the deme for (size_t i = 0; i < NP; ++i) { - do { /* Pick a random population member */ - /* Endless loop for NP < 2 !!! */ - r1 = p_idx(); - } while (r1==i); - - do { /* Pick a random population member */ - /* Endless loop for NP < 3 !!! */ - r2 = p_idx(); - } while ((r2==i) || (r2==r1)); - - do { /* Pick a random population member */ - /* Endless loop for NP < 4 !!! */ - r3 = p_idx(); - } while ((r3==i) || (r3==r1) || (r3==r2)); - - do { /* Pick a random population member */ - /* Endless loop for NP < 5 !!! */ - r4 = p_idx(); - } while ((r4==i) || (r4==r1) || (r4==r2) || (r4==r3)); - - do { /* Pick a random population member */ - /* Endless loop for NP < 6 !!! */ - r5 = p_idx(); - } while ((r5==i) || (r5==r1) || (r5==r2) || (r5==r3) || (r5==r4)); - do { /* Pick a random population member */ - /* Endless loop for NP < 7 !!! */ - r6 = p_idx(); - } while ((r6==i) || (r6==r1) || (r6==r2) || (r6==r3) || (r6==r4) || (r6==r5)); - do { /* Pick a random population member */ - /* Endless loop for NP < 8 !!! */ - r7 = p_idx(); - } while ((r7==i) || (r7==r1) || (r7==r2) || (r7==r3) || (r7==r4) || (r7==r5) || (r7==r6)); + if (NP < 21) { + std::vector sample; + generate_sample(sample, NP, i); + r1 = sample[0]; + r2 = sample[1]; + r3 = sample[2]; + r4 = sample[3]; + r5 = sample[4]; + r6 = sample[5]; + r7 = sample[6]; + } else { + do { /* Pick a random population member */ + /* Endless loop for NP < 2 !!! */ + r1 = p_idx(); + } while (r1==i); + + do { /* Pick a random population member */ + /* Endless loop for NP < 3 !!! */ + r2 = p_idx(); + } while ((r2==i) || (r2==r1)); + + do { /* Pick a random population member */ + /* Endless loop for NP < 4 !!! */ + r3 = p_idx(); + } while ((r3==i) || (r3==r1) || (r3==r2)); + + do { /* Pick a random population member */ + /* Endless loop for NP < 5 !!! */ + r4 = p_idx(); + } while ((r4==i) || (r4==r1) || (r4==r2) || (r4==r3)); + + do { /* Pick a random population member */ + /* Endless loop for NP < 6 !!! */ + r5 = p_idx(); + } while ((r5==i) || (r5==r1) || (r5==r2) || (r5==r3) || (r5==r4)); + do { /* Pick a random population member */ + /* Endless loop for NP < 7 !!! */ + r6 = p_idx(); + } while ((r6==i) || (r6==r1) || (r6==r2) || (r6==r3) || (r6==r4) || (r6==r5)); + do { /* Pick a random population member */ + /* Endless loop for NP < 8 !!! */ + r7 = p_idx(); + } while ((r7==i) || (r7==r1) || (r7==r2) || (r7==r3) || (r7==r4) || (r7==r5) || (r7==r6)); + } // Adapt amplification factor and crossover probability double F=0, CR=0; From 255ba7810ee4b4c31c4342b4ffd11da157b078b4 Mon Sep 17 00:00:00 2001 From: Eduard Nicodei Date: Sun, 8 Mar 2015 15:34:22 +0000 Subject: [PATCH 4/4] Optimize sampling method in jDE. --- src/algorithm/jde.cpp | 83 ++++++++++++++++++------------------------- src/algorithm/jde.h | 1 - 2 files changed, 35 insertions(+), 49 deletions(-) diff --git a/src/algorithm/jde.cpp b/src/algorithm/jde.cpp index 001238f7..5f3eb603 100644 --- a/src/algorithm/jde.cpp +++ b/src/algorithm/jde.cpp @@ -187,18 +187,44 @@ void jde::evolve(population &pop) const } } + std::vector elements; + if (NP < 21) { + // Add elements in order. + for (size_t i = 0; i < NP; ++i) { + elements.push_back(i); + } + } + //Start of the loop through the deme for (size_t i = 0; i < NP; ++i) { if (NP < 21) { - std::vector sample; - generate_sample(sample, NP, i); - r1 = sample[0]; - r2 = sample[1]; - r3 = sample[2]; - r4 = sample[3]; - r5 = sample[4]; - r6 = sample[5]; - r7 = sample[6]; + bool i_was_sampled = false; + size_t sampled_i_pos; + // Shuffle 8 elements. + // If 'i' is not picked, then we only use 7 of them. + for (size_t pos = 0; pos < 8; ++pos) { + // uniform_int<> rnd(a,b) gives values in the range [a,b] not [a,b). + boost::uniform_int rnd_idx(0, NP - pos - 1); + size_t rnd = rnd_idx(m_urng); + if (elements[rnd] == i) { + i_was_sampled = true; + // Remember where we put i. + sampled_i_pos = NP - pos - 1; + } + std::swap(elements[rnd], elements[NP - pos - 1]); + } + + if (i_was_sampled) { + std::swap(elements[sampled_i_pos], elements[NP - 7 - 1]); + } + + r1 = elements[NP - 1]; + r2 = elements[NP - 2]; + r3 = elements[NP - 3]; + r4 = elements[NP - 4]; + r5 = elements[NP - 5]; + r6 = elements[NP - 6]; + r7 = elements[NP - 7]; } else { do { /* Pick a random population member */ /* Endless loop for NP < 2 !!! */ @@ -593,45 +619,6 @@ std::string jde::human_readable_extra() const return s.str(); } -// Helper function. -/** - * Used to speed up evolve()'s way of selecting population members. - * Generate a random sample of 7 different elements, from {0..(NP - 1)} / {current_element}. - * - * @param[out] sample space holder for the selected elements - * @param[in] NP the "population size" - * @param[in] current_element this element will not be included in the final sample. - */ -void jde::generate_sample(std::vector &sample, const size_t NP, const size_t current_element) const -{ - std::vector elements; - size_t i; - - // Add elements in order. Skip current_element. - for (i = 0; i < NP; ++i) { - if (i == current_element) { - continue; - } - elements.push_back(i); - } - - // Shuffle elements. - for (i = 0; i < 7; ++i) { - // uniform_int<> rnd(a,b) gives values in the range [a,b] not [a,b). - // We have NP - 1 elements, therefore the range is [0, NP - i - 2]. - boost::uniform_int rnd_idx(0, NP - i - 2); - std::swap(elements[rnd_idx(m_urng)], elements[NP - i - 2]); - } - - // Create sample of the first 7 elements. - if (sample.size() > 0) { - sample.erase(sample.begin(), sample.end()); - } - for (i = 0; i < 7; ++i) { - sample.push_back(elements[elements.size() - i - 1]); - } -} - }} //namespaces BOOST_CLASS_EXPORT_IMPLEMENT(pagmo::algorithm::jde) diff --git a/src/algorithm/jde.h b/src/algorithm/jde.h index e9cee135..d2fa0a08 100644 --- a/src/algorithm/jde.h +++ b/src/algorithm/jde.h @@ -68,7 +68,6 @@ class __PAGMO_VISIBLE jde : public base base_ptr clone() const; void evolve(population &) const; std::string get_name() const; - void generate_sample(std::vector &, const size_t, const size_t) const; protected: std::string human_readable_extra() const;