From d9eb8eee7aed4b683e841569da88e186ccc7a642 Mon Sep 17 00:00:00 2001 From: Tarcisio Fischer Date: Tue, 5 Oct 2021 15:30:56 -0300 Subject: [PATCH 1/7] Keeping PSO variables at memory so that consecutive calls to evolve are equal --- include/pagmo/algorithms/pso.hpp | 11 ++++- src/algorithms/pso.cpp | 70 ++++++++++++++++++++++---------- tests/pso.cpp | 52 ++++++++++++++++++++++++ 3 files changed, 111 insertions(+), 22 deletions(-) diff --git a/include/pagmo/algorithms/pso.hpp b/include/pagmo/algorithms/pso.hpp index c36a15b75..6f8d74978 100644 --- a/include/pagmo/algorithms/pso.hpp +++ b/include/pagmo/algorithms/pso.hpp @@ -31,6 +31,7 @@ see https://www.gnu.org/licenses/. */ #include #include +#include #include #include @@ -254,9 +255,17 @@ class PAGMO_DLL_PUBLIC pso unsigned m_neighb_param; // memory bool m_memory; + // Particle position for memory usage only + mutable std::optional> m_memory_X; + mutable std::optional> m_memory_lbX; + mutable std::optional> m_memory_fit; + mutable std::optional> m_memory_lbfit; + mutable std::optional m_memory_best_fit; + using population_size_t = decltype(std::declval().size()); + mutable std::optional>> m_memory_neighb; + mutable std::optional m_memory_best_neighb; // paricles' velocities mutable std::vector m_V; - mutable detail::random_engine_type m_e; unsigned m_seed; unsigned m_verbosity; diff --git a/src/algorithms/pso.cpp b/src/algorithms/pso.cpp index a8ba39d7a..f0049050c 100644 --- a/src/algorithms/pso.cpp +++ b/src/algorithms/pso.cpp @@ -179,12 +179,22 @@ population pso::evolve(population pop) const } // Copy the particle positions and their fitness - for (decltype(swarm_size) i = 0u; i < swarm_size; ++i) { - X[i] = pop.get_x()[i]; - lbX[i] = pop.get_x()[i]; + // If calling from memory, the positions from last run may not be the same as the best population + // so it is make a correction here + if (m_memory && m_memory_X) { + X = *m_memory_X; + lbX = *m_memory_lbX; + + fit = *m_memory_fit; + lbfit = *m_memory_lbfit; + } else { + for (decltype(swarm_size) i = 0u; i < swarm_size; ++i) { + X[i] = pop.get_x()[i]; + lbX[i] = pop.get_x()[i]; - fit[i] = pop.get_f()[i]; - lbfit[i] = pop.get_f()[i]; + fit[i] = pop.get_f()[i]; + lbfit[i] = pop.get_f()[i]; + } } // Initialize the particle velocities if necessary @@ -198,25 +208,31 @@ population pso::evolve(population pop) const } // Initialize the Swarm's topology - switch (m_neighb_type) { - case 1: - initialize_topology__gbest(pop, best_neighb, best_fit, neighb); - break; - case 3: - initialize_topology__von(neighb); - break; - case 4: - initialize_topology__adaptive_random(neighb); - // need to track improvements in best found fitness, to know when to rewire - best_fit = pop.get_f()[pop.best_idx()]; - break; - case 2: - default: - initialize_topology__lbest(neighb); + if (m_memory && m_memory_neighb) { + neighb = *m_memory_neighb; + best_fit = *m_memory_best_fit; + best_neighb = *m_memory_best_neighb; + } else { + switch (m_neighb_type) { + case 1: + initialize_topology__gbest(pop, best_neighb, best_fit, neighb); + break; + case 3: + initialize_topology__von(neighb); + break; + case 4: + initialize_topology__adaptive_random(neighb); + // need to track improvements in best found fitness, to know when to rewire + best_fit = pop.get_f()[pop.best_idx()]; + break; + case 2: + default: + initialize_topology__lbest(neighb); + } } // auxiliary variables specific to the Fully Informed Particle Swarm variant double acceleration_coefficient = m_eta1 + m_eta2; - double sum_forces; + double sum_forces = 0.; double r1 = 0.; double r2 = 0.; @@ -439,6 +455,18 @@ population pso::evolve(population pop) const for (decltype(swarm_size) i = 0u; i < swarm_size; ++i) { pop.set_xf(i, lbX[i], lbfit[i]); } + + // Keep memory variables only if asked for + if (m_memory) { + m_memory_X = X; + m_memory_lbX = lbX; + m_memory_fit = fit; + m_memory_lbfit = lbfit; + m_memory_best_fit = best_fit; + m_memory_neighb = neighb; + m_memory_best_neighb = best_neighb; + } + return pop; } diff --git a/tests/pso.cpp b/tests/pso.cpp index 122111047..a44f94cb5 100644 --- a/tests/pso.cpp +++ b/tests/pso.cpp @@ -134,6 +134,7 @@ BOOST_AUTO_TEST_CASE(evolve_test) } } } + BOOST_AUTO_TEST_CASE(setters_getters_test) { pso user_algo{5000u, 0.79, 2., 2., 0.1, 5u, 2u, 4u, false, 23u}; @@ -184,3 +185,54 @@ BOOST_AUTO_TEST_CASE(serialization_test) BOOST_CHECK_CLOSE(std::get<5>(before_log[i]), std::get<5>(after_log[i]), 1e-8); } } + +BOOST_AUTO_TEST_CASE(pso_memory_test) +{ + // We check here that when memory is true calling evolve(pop) two times on 1 gen + // is the same as calling 1 time evolve with 2 gens + auto omega = 0.5d; + auto eta1 = 0.5d; + auto eta2 = 0.5d; + auto max_vel = 0.5d; + auto neighb_param = 4u; + auto seed = 42u; + auto pop_size = 10u; + + for (auto variant = 1u; variant <= 6; ++variant) { + for (auto neighb_type = 1u; neighb_type <= 4; ++neighb_type) { + auto log1 = ([&]() { + auto n_generations = 1u; + auto memory = true; + pso user_algo{n_generations, omega, eta1, eta2, max_vel, variant, neighb_type, neighb_param, memory, seed}; + user_algo.set_verbosity(1u); + problem prob{rosenbrock{25u}}; + population pop{prob, pop_size, seed}; + pop = user_algo.evolve(pop); + pop = user_algo.evolve(pop); + pop = user_algo.evolve(pop); + return user_algo.get_log(); + })(); + + auto log2 = ([&]() { + auto n_generations = 3u; + auto memory = false; + pso user_algo{n_generations, omega, eta1, eta2, max_vel, variant, neighb_type, neighb_param, memory, seed}; + user_algo.set_verbosity(1u); + problem prob{rosenbrock{25u}}; + population pop{prob, pop_size, seed}; + pop = user_algo.evolve(pop); + return user_algo.get_log(); + })(); + + // indexes 0 (Gen) and 1 (Fevals) may be different + // Check index 2 (gbest) + BOOST_CHECK_CLOSE(std::get<2>(log1[0]), std::get<2>(log2[2]), 1e-8); + // Check index 3 (Mean Vel.) + BOOST_CHECK_CLOSE(std::get<3>(log1[0]), std::get<3>(log2[2]), 1e-8); + // Check index 4 (Mean lbest) + BOOST_CHECK_CLOSE(std::get<4>(log1[0]), std::get<4>(log2[2]), 1e-8); + // Check index 5 (Avg. Dist.) + BOOST_CHECK_CLOSE(std::get<5>(log1[0]), std::get<5>(log2[2]), 1e-8); + } + } +} From e3b6d08798fec8d9261fa3406f9e2594c6c64237 Mon Sep 17 00:00:00 2001 From: Tarcisio Fischer Date: Tue, 5 Oct 2021 15:39:06 -0300 Subject: [PATCH 2/7] Refactoring: Move memory data to specific struct --- include/pagmo/algorithms/pso.hpp | 23 ++++++++++++++--------- src/algorithms/pso.cpp | 26 ++++++++++---------------- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/include/pagmo/algorithms/pso.hpp b/include/pagmo/algorithms/pso.hpp index 6f8d74978..1a2298ffb 100644 --- a/include/pagmo/algorithms/pso.hpp +++ b/include/pagmo/algorithms/pso.hpp @@ -224,6 +224,18 @@ class PAGMO_DLL_PUBLIC pso } private: + struct memory { + using population_size_t = decltype(std::declval().size()); + + std::vector m_X; + std::vector m_lbX; + std::vector m_fit; + std::vector m_lbfit; + vector_double m_best_fit; + std::vector> m_neighb; + vector_double m_best_neighb; + }; + // Object serialization friend class boost::serialization::access; template @@ -255,15 +267,8 @@ class PAGMO_DLL_PUBLIC pso unsigned m_neighb_param; // memory bool m_memory; - // Particle position for memory usage only - mutable std::optional> m_memory_X; - mutable std::optional> m_memory_lbX; - mutable std::optional> m_memory_fit; - mutable std::optional> m_memory_lbfit; - mutable std::optional m_memory_best_fit; - using population_size_t = decltype(std::declval().size()); - mutable std::optional>> m_memory_neighb; - mutable std::optional m_memory_best_neighb; + mutable std::optional m_memory_data; + // paricles' velocities mutable std::vector m_V; mutable detail::random_engine_type m_e; diff --git a/src/algorithms/pso.cpp b/src/algorithms/pso.cpp index f0049050c..8f0774b42 100644 --- a/src/algorithms/pso.cpp +++ b/src/algorithms/pso.cpp @@ -181,12 +181,12 @@ population pso::evolve(population pop) const // Copy the particle positions and their fitness // If calling from memory, the positions from last run may not be the same as the best population // so it is make a correction here - if (m_memory && m_memory_X) { - X = *m_memory_X; - lbX = *m_memory_lbX; + if (m_memory && m_memory_data) { + X = m_memory_data->m_X; + lbX = m_memory_data->m_lbX; - fit = *m_memory_fit; - lbfit = *m_memory_lbfit; + fit = m_memory_data->m_fit; + lbfit = m_memory_data->m_lbfit; } else { for (decltype(swarm_size) i = 0u; i < swarm_size; ++i) { X[i] = pop.get_x()[i]; @@ -208,10 +208,10 @@ population pso::evolve(population pop) const } // Initialize the Swarm's topology - if (m_memory && m_memory_neighb) { - neighb = *m_memory_neighb; - best_fit = *m_memory_best_fit; - best_neighb = *m_memory_best_neighb; + if (m_memory && m_memory_data) { + neighb = m_memory_data->m_neighb; + best_fit = m_memory_data->m_best_fit; + best_neighb = m_memory_data->m_best_neighb; } else { switch (m_neighb_type) { case 1: @@ -458,13 +458,7 @@ population pso::evolve(population pop) const // Keep memory variables only if asked for if (m_memory) { - m_memory_X = X; - m_memory_lbX = lbX; - m_memory_fit = fit; - m_memory_lbfit = lbfit; - m_memory_best_fit = best_fit; - m_memory_neighb = neighb; - m_memory_best_neighb = best_neighb; + m_memory_data = pso::memory{X, lbX, fit, lbfit, best_fit, neighb, best_neighb}; } return pop; From 003f435f088d3d41be1d513d23010c1af61e0aae Mon Sep 17 00:00:00 2001 From: Tarcisio Fischer Date: Wed, 6 Oct 2021 09:57:40 -0300 Subject: [PATCH 3/7] Add PSO memory object serialization --- include/pagmo/algorithms/pso.hpp | 10 ++++- src/algorithms/pso.cpp | 11 +++++- tests/pso.cpp | 65 +++++++++++++++++++++++++++----- 3 files changed, 72 insertions(+), 14 deletions(-) diff --git a/include/pagmo/algorithms/pso.hpp b/include/pagmo/algorithms/pso.hpp index 1a2298ffb..77240c6c0 100644 --- a/include/pagmo/algorithms/pso.hpp +++ b/include/pagmo/algorithms/pso.hpp @@ -29,6 +29,8 @@ see https://www.gnu.org/licenses/. */ #ifndef PAGMO_ALGORITHMS_PSO_HPP #define PAGMO_ALGORITHMS_PSO_HPP +#include +#include #include #include #include @@ -234,6 +236,10 @@ class PAGMO_DLL_PUBLIC pso vector_double m_best_fit; std::vector> m_neighb; vector_double m_best_neighb; + + // Object serialization + template + void serialize(Archive &, unsigned); }; // Object serialization @@ -267,9 +273,9 @@ class PAGMO_DLL_PUBLIC pso unsigned m_neighb_param; // memory bool m_memory; - mutable std::optional m_memory_data; + mutable boost::optional m_memory_data; - // paricles' velocities + // particles' velocities mutable std::vector m_V; mutable detail::random_engine_type m_e; unsigned m_seed; diff --git a/src/algorithms/pso.cpp b/src/algorithms/pso.cpp index 8f0774b42..1d57c14eb 100644 --- a/src/algorithms/pso.cpp +++ b/src/algorithms/pso.cpp @@ -503,8 +503,15 @@ std::string pso::get_extra_info() const template void pso::serialize(Archive &ar, unsigned) { - detail::archive(ar, m_max_gen, m_omega, m_eta1, m_eta2, m_max_vel, m_variant, m_neighb_type, m_neighb_param, m_e, - m_seed, m_verbosity, m_log); + detail::archive(ar, m_max_gen, m_omega, m_eta1, m_eta2, m_max_vel, m_variant, m_neighb_type, m_neighb_param, + m_memory, m_memory_data, m_V, m_e, m_seed, m_verbosity, m_log); +} + +// Object'm memory serialization +template +void pso::memory::serialize(Archive &ar, unsigned) +{ + detail::archive(ar, m_X, m_lbX, m_fit, m_lbfit, m_best_fit, m_neighb, m_best_neighb); } /** diff --git a/tests/pso.cpp b/tests/pso.cpp index a44f94cb5..a64e85376 100644 --- a/tests/pso.cpp +++ b/tests/pso.cpp @@ -203,25 +203,27 @@ BOOST_AUTO_TEST_CASE(pso_memory_test) auto log1 = ([&]() { auto n_generations = 1u; auto memory = true; - pso user_algo{n_generations, omega, eta1, eta2, max_vel, variant, neighb_type, neighb_param, memory, seed}; - user_algo.set_verbosity(1u); + algorithm algo{ + pso{n_generations, omega, eta1, eta2, max_vel, variant, neighb_type, neighb_param, memory, seed}}; + algo.set_verbosity(1u); problem prob{rosenbrock{25u}}; population pop{prob, pop_size, seed}; - pop = user_algo.evolve(pop); - pop = user_algo.evolve(pop); - pop = user_algo.evolve(pop); - return user_algo.get_log(); + pop = algo.evolve(pop); + pop = algo.evolve(pop); + pop = algo.evolve(pop); + return algo.extract()->get_log(); })(); auto log2 = ([&]() { auto n_generations = 3u; auto memory = false; - pso user_algo{n_generations, omega, eta1, eta2, max_vel, variant, neighb_type, neighb_param, memory, seed}; - user_algo.set_verbosity(1u); + algorithm algo{ + pso{n_generations, omega, eta1, eta2, max_vel, variant, neighb_type, neighb_param, memory, seed}}; + algo.set_verbosity(1u); problem prob{rosenbrock{25u}}; population pop{prob, pop_size, seed}; - pop = user_algo.evolve(pop); - return user_algo.get_log(); + pop = algo.evolve(pop); + return algo.extract()->get_log(); })(); // indexes 0 (Gen) and 1 (Fevals) may be different @@ -233,6 +235,49 @@ BOOST_AUTO_TEST_CASE(pso_memory_test) BOOST_CHECK_CLOSE(std::get<4>(log1[0]), std::get<4>(log2[2]), 1e-8); // Check index 5 (Avg. Dist.) BOOST_CHECK_CLOSE(std::get<5>(log1[0]), std::get<5>(log2[2]), 1e-8); + + // Make sure serializing and deserializing the results will give the same answer + auto serialize_and_deserialize = [](algorithm &algo) { + std::stringstream ss; + { + boost::archive::binary_oarchive oarchive(ss); + oarchive << algo; + } + algo = algorithm{}; + { + boost::archive::binary_iarchive iarchive(ss); + iarchive >> algo; + } + }; + auto log3 = ([&]() { + auto n_generations = 1u; + auto memory = true; + algorithm algo{ + pso{n_generations, omega, eta1, eta2, max_vel, variant, neighb_type, neighb_param, memory, seed}}; + algo.set_verbosity(1u); + problem prob{rosenbrock{25u}}; + population pop{prob, pop_size, seed}; + pop = algo.evolve(pop); + serialize_and_deserialize(algo); + pop = algo.evolve(pop); + serialize_and_deserialize(algo); + pop = algo.evolve(pop); + return algo.extract()->get_log(); + })(); + // While comparing the serialized vs non-serialized versions, all logs must be the same. + BOOST_CHECK_EQUAL(log1.size(), log3.size()); + // Check index 0 (Gen) + BOOST_CHECK_EQUAL(std::get<0>(log1[0]), std::get<0>(log3[0])); + // Check index 1 (Fevals) + BOOST_CHECK_EQUAL(std::get<1>(log1[0]), std::get<1>(log3[0])); + // Check index 2 (gbest) + BOOST_CHECK_CLOSE(std::get<2>(log1[0]), std::get<2>(log3[0]), 1e-8); + // Check index 3 (Mean Vel.) + BOOST_CHECK_CLOSE(std::get<3>(log1[0]), std::get<3>(log3[0]), 1e-8); + // Check index 4 (Mean lbest) + BOOST_CHECK_CLOSE(std::get<4>(log1[0]), std::get<4>(log3[0]), 1e-8); + // Check index 5 (Avg. Dist.) + BOOST_CHECK_CLOSE(std::get<5>(log1[0]), std::get<5>(log3[0]), 1e-8); } } } From e74abb331fb4802da88cc8407d16af79bce4f878 Mon Sep 17 00:00:00 2001 From: Tarcisio Fischer Date: Wed, 6 Oct 2021 10:13:24 -0300 Subject: [PATCH 4/7] Code Review: Replace population size type --- include/pagmo/algorithms/pso.hpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/pagmo/algorithms/pso.hpp b/include/pagmo/algorithms/pso.hpp index 77240c6c0..2eb95b58a 100644 --- a/include/pagmo/algorithms/pso.hpp +++ b/include/pagmo/algorithms/pso.hpp @@ -227,14 +227,12 @@ class PAGMO_DLL_PUBLIC pso private: struct memory { - using population_size_t = decltype(std::declval().size()); - std::vector m_X; std::vector m_lbX; std::vector m_fit; std::vector m_lbfit; vector_double m_best_fit; - std::vector> m_neighb; + std::vector> m_neighb; vector_double m_best_neighb; // Object serialization From c4ef9bf167699b912d6b22e80f39a49c529eb140 Mon Sep 17 00:00:00 2001 From: Tarcisio Fischer Date: Thu, 7 Oct 2021 08:24:40 -0300 Subject: [PATCH 5/7] Code Review: Header cleanup and build fixes --- include/pagmo/algorithms/pso.hpp | 2 -- src/algorithms/pso.cpp | 4 ++++ tests/pso.cpp | 8 ++++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/include/pagmo/algorithms/pso.hpp b/include/pagmo/algorithms/pso.hpp index 2eb95b58a..afbc64979 100644 --- a/include/pagmo/algorithms/pso.hpp +++ b/include/pagmo/algorithms/pso.hpp @@ -30,10 +30,8 @@ see https://www.gnu.org/licenses/. */ #define PAGMO_ALGORITHMS_PSO_HPP #include -#include #include #include -#include #include #include diff --git a/src/algorithms/pso.cpp b/src/algorithms/pso.cpp index 1d57c14eb..cf71adb66 100644 --- a/src/algorithms/pso.cpp +++ b/src/algorithms/pso.cpp @@ -46,6 +46,10 @@ see https://www.gnu.org/licenses/. */ #include #include +// NOTE: apparently this must be included *after* +// the other serialization headers. +#include + namespace pagmo { diff --git a/tests/pso.cpp b/tests/pso.cpp index a64e85376..384da8c03 100644 --- a/tests/pso.cpp +++ b/tests/pso.cpp @@ -190,10 +190,10 @@ BOOST_AUTO_TEST_CASE(pso_memory_test) { // We check here that when memory is true calling evolve(pop) two times on 1 gen // is the same as calling 1 time evolve with 2 gens - auto omega = 0.5d; - auto eta1 = 0.5d; - auto eta2 = 0.5d; - auto max_vel = 0.5d; + auto omega = 0.5; + auto eta1 = 0.5; + auto eta2 = 0.5; + auto max_vel = 0.5; auto neighb_param = 4u; auto seed = 42u; auto pop_size = 10u; From 091c1f45f5723decd5b3bd968e21a6a1f78fc4d5 Mon Sep 17 00:00:00 2001 From: Tarcisio Fischer Date: Thu, 7 Oct 2021 08:33:28 -0300 Subject: [PATCH 6/7] Code Review: Move m_V to memory --- include/pagmo/algorithms/pso.hpp | 3 +- src/algorithms/pso.cpp | 62 ++++++++++++++++---------------- 2 files changed, 33 insertions(+), 32 deletions(-) diff --git a/include/pagmo/algorithms/pso.hpp b/include/pagmo/algorithms/pso.hpp index afbc64979..11861c0f8 100644 --- a/include/pagmo/algorithms/pso.hpp +++ b/include/pagmo/algorithms/pso.hpp @@ -225,6 +225,7 @@ class PAGMO_DLL_PUBLIC pso private: struct memory { + std::vector m_V; std::vector m_X; std::vector m_lbX; std::vector m_fit; @@ -271,8 +272,6 @@ class PAGMO_DLL_PUBLIC pso bool m_memory; mutable boost::optional m_memory_data; - // particles' velocities - mutable std::vector m_V; mutable detail::random_engine_type m_e; unsigned m_seed; unsigned m_verbosity; diff --git a/src/algorithms/pso.cpp b/src/algorithms/pso.cpp index cf71adb66..7cc487836 100644 --- a/src/algorithms/pso.cpp +++ b/src/algorithms/pso.cpp @@ -77,7 +77,7 @@ constexpr int pso_vonNeumann_neighb_diff[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, pso::pso(unsigned gen, double omega, double eta1, double eta2, double max_vel, unsigned variant, unsigned neighb_type, unsigned neighb_param, bool memory, unsigned seed) : m_max_gen(gen), m_omega(omega), m_eta1(eta1), m_eta2(eta2), m_max_vel(max_vel), m_variant(variant), - m_neighb_type(neighb_type), m_neighb_param(neighb_param), m_memory(memory), m_V(), m_e(seed), m_seed(seed), + m_neighb_type(neighb_type), m_neighb_param(neighb_param), m_memory(memory), m_e(seed), m_seed(seed), m_verbosity(0u), m_log() { if (m_omega < 0. || m_omega > 1.) { @@ -202,11 +202,13 @@ population pso::evolve(population pop) const } // Initialize the particle velocities if necessary - if ((m_V.size() != swarm_size) || (!m_memory)) { - m_V = std::vector(swarm_size, dummy); + std::vector V(swarm_size, dummy); + if (m_memory && m_memory_data) { + V = m_memory_data->m_V; + } else { for (decltype(swarm_size) i = 0u; i < swarm_size; ++i) { for (decltype(dim) j = 0u; j < dim; ++j) { - m_V[i][j] = uniform_real_from_range(minv[j], maxv[j], m_e); + V[i][j] = uniform_real_from_range(minv[j], maxv[j], m_e); } } } @@ -262,8 +264,8 @@ population pso::evolve(population pop) const for (decltype(dim) d = 0u; d < dim; ++d) { r1 = drng(m_e); r2 = drng(m_e); - m_V[p][d] = m_omega * m_V[p][d] + m_eta1 * r1 * (lbX[p][d] - X[p][d]) - + m_eta2 * r2 * (best_neighb[d] - X[p][d]); + V[p][d] = m_omega * V[p][d] + m_eta1 * r1 * (lbX[p][d] - X[p][d]) + + m_eta2 * r2 * (best_neighb[d] - X[p][d]); } } @@ -273,8 +275,8 @@ population pso::evolve(population pop) const else if (m_variant == 2u) { for (decltype(dim) d = 0u; d < dim; ++d) { r1 = drng(m_e); - m_V[p][d] = m_omega * m_V[p][d] + m_eta1 * r1 * (lbX[p][d] - X[p][d]) - + m_eta2 * r1 * (best_neighb[d] - X[p][d]); + V[p][d] = m_omega * V[p][d] + m_eta1 * r1 * (lbX[p][d] - X[p][d]) + + m_eta2 * r1 * (best_neighb[d] - X[p][d]); } } @@ -284,8 +286,8 @@ population pso::evolve(population pop) const r1 = drng(m_e); r2 = drng(m_e); for (decltype(dim) d = 0u; d < dim; ++d) { - m_V[p][d] = m_omega * m_V[p][d] + m_eta1 * r1 * (lbX[p][d] - X[p][d]) - + m_eta2 * r2 * (best_neighb[d] - X[p][d]); + V[p][d] = m_omega * V[p][d] + m_eta1 * r1 * (lbX[p][d] - X[p][d]) + + m_eta2 * r2 * (best_neighb[d] - X[p][d]); } } @@ -295,8 +297,8 @@ population pso::evolve(population pop) const else if (m_variant == 4u) { r1 = drng(m_e); for (decltype(dim) d = 0u; d < dim; ++d) { - m_V[p][d] = m_omega * m_V[p][d] + m_eta1 * r1 * (lbX[p][d] - X[p][d]) - + m_eta2 * r1 * (best_neighb[d] - X[p][d]); + V[p][d] = m_omega * V[p][d] + m_eta1 * r1 * (lbX[p][d] - X[p][d]) + + m_eta2 * r1 * (best_neighb[d] - X[p][d]); } } @@ -317,9 +319,9 @@ population pso::evolve(population pop) const for (decltype(dim) d = 0u; d < dim; ++d) { r1 = drng(m_e); r2 = drng(m_e); - m_V[p][d] = m_omega - * (m_V[p][d] + m_eta1 * r1 * (lbX[p][d] - X[p][d]) - + m_eta2 * r2 * (best_neighb[d] - X[p][d])); + V[p][d] + = m_omega + * (V[p][d] + m_eta1 * r1 * (lbX[p][d] - X[p][d]) + m_eta2 * r2 * (best_neighb[d] - X[p][d])); } } @@ -339,7 +341,7 @@ population pso::evolve(population pop) const for (decltype(neighb[p].size()) n = 0u; n < neighb[p].size(); ++n) { sum_forces += drng(m_e) * acceleration_coefficient * (lbX[neighb[p][n]][d] - X[p][d]); } - m_V[p][d] = m_omega * (m_V[p][d] + sum_forces / static_cast(neighb[p].size())); + V[p][d] = m_omega * (V[p][d] + sum_forces / static_cast(neighb[p].size())); } } @@ -347,28 +349,28 @@ population pso::evolve(population pop) const // and we perform the position update and the feasibility correction for (decltype(dim) d = 0u; d < dim; ++d) { - if (m_V[p][d] > maxv[d]) { - m_V[p][d] = maxv[d]; + if (V[p][d] > maxv[d]) { + V[p][d] = maxv[d]; } - else if (m_V[p][d] < minv[d]) { - m_V[p][d] = minv[d]; + else if (V[p][d] < minv[d]) { + V[p][d] = minv[d]; } // update position - new_x = X[p][d] + m_V[p][d]; + new_x = X[p][d] + V[p][d]; // feasibility correction // (velocity updated to that which would have taken the previous position // to the newly corrected feasible position) if (new_x < lb[d]) { new_x = lb[d]; - m_V[p][d] = 0.; + V[p][d] = 0.; // new_x = boost::uniform_real(lb[d],ub[d])(m_drng); // V[p][d] = new_x - X[p][d]; } else if (new_x > ub[d]) { new_x = ub[d]; - m_V[p][d] = 0.; + V[p][d] = 0.; // new_x = boost::uniform_real(lb[d],ub[d])(m_drng); // V[p][d] = new_x - X[p][d]; } @@ -413,13 +415,13 @@ population pso::evolve(population pop) const auto best = local_fits[static_cast(idx_best)]; // We compute a measure for the average particle velocity across the swarm auto mean_velocity = 0.; - for (decltype(m_V.size()) i = 0u; i < m_V.size(); ++i) { - for (decltype(m_V[i].size()) j = 0u; j < m_V[i].size(); ++j) { + for (decltype(V.size()) i = 0u; i < V.size(); ++i) { + for (decltype(V[i].size()) j = 0u; j < V[i].size(); ++j) { if (ub[j] > lb[j]) { - mean_velocity += std::abs(m_V[i][j] / (ub[j] - lb[j])); + mean_velocity += std::abs(V[i][j] / (ub[j] - lb[j])); } // else 0 } - mean_velocity /= static_cast(m_V[i].size()); + mean_velocity /= static_cast(V[i].size()); } // We compute the average distance across particles (NOTE: N^2 complexity) auto avg_dist = 0.; @@ -462,7 +464,7 @@ population pso::evolve(population pop) const // Keep memory variables only if asked for if (m_memory) { - m_memory_data = pso::memory{X, lbX, fit, lbfit, best_fit, neighb, best_neighb}; + m_memory_data = pso::memory{V, X, lbX, fit, lbfit, best_fit, neighb, best_neighb}; } return pop; @@ -508,14 +510,14 @@ template void pso::serialize(Archive &ar, unsigned) { detail::archive(ar, m_max_gen, m_omega, m_eta1, m_eta2, m_max_vel, m_variant, m_neighb_type, m_neighb_param, - m_memory, m_memory_data, m_V, m_e, m_seed, m_verbosity, m_log); + m_memory, m_memory_data, m_e, m_seed, m_verbosity, m_log); } // Object'm memory serialization template void pso::memory::serialize(Archive &ar, unsigned) { - detail::archive(ar, m_X, m_lbX, m_fit, m_lbfit, m_best_fit, m_neighb, m_best_neighb); + detail::archive(ar, m_V, m_X, m_lbX, m_fit, m_lbfit, m_best_fit, m_neighb, m_best_neighb); } /** From 462e1c5283c1f4b1a810db07a715a80d71b78cb0 Mon Sep 17 00:00:00 2001 From: Tarcisio Fischer Date: Thu, 7 Oct 2021 09:19:20 -0300 Subject: [PATCH 7/7] Replace broken paper link for genetic operators --- src/utils/genetic_operators.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/genetic_operators.cpp b/src/utils/genetic_operators.cpp index b5e915e69..a0ddd6fd2 100644 --- a/src/utils/genetic_operators.cpp +++ b/src/utils/genetic_operators.cpp @@ -285,7 +285,7 @@ std::pair sbx_crossover(const vector_double &paren /** * This function performs the polynomial mutation proposed by Agrawal and Deb over some chromosome. * - * @see https://www.iitk.ac.in/kangal/papers/k2012016.pdf + * @see https://dl.acm.org/doi/10.1504/IJAISC.2014.059280 * * Example: * @code{.unparsed}