LCOV - code coverage report
Current view: top level - maze - Memetic.h (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 123 201 61.2 %
Date: 2024-10-11 08:09:47 Functions: 14 20 70.0 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             : Copyright (c) 2019 Jakub Rydzewski (jr@fizyka.umk.pl). All rights reserved.
       3             : 
       4             : See http://www.maze-code.github.io for more information.
       5             : 
       6             : This file is part of maze.
       7             : 
       8             : maze is free software: you can redistribute it and/or modify it under the
       9             : terms of the GNU Lesser General Public License as published by the Free
      10             : Software Foundation, either version 3 of the License, or (at your option)
      11             : any later version.
      12             : 
      13             : maze is distributed in the hope that it will be useful, but WITHOUT ANY
      14             : WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      15             : FOR A PARTICULAR PURPOSE.
      16             : 
      17             : See the GNU Lesser General Public License for more details.
      18             : 
      19             : You should have received a copy of the GNU Lesser General Public License
      20             : along with maze. If not, see <https://www.gnu.org/licenses/>.
      21             : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
      22             : #ifndef __PLUMED_maze_Memetic_h
      23             : #define __PLUMED_maze_Memetic_h
      24             : 
      25             : /**
      26             :  * @file Memetic.h
      27             :  *
      28             :  * @author J. Rydzewski (jr@fizyka.umk.pl)
      29             :  */
      30             : 
      31             : #include "core/ActionRegister.h"
      32             : 
      33             : #include "Core.h"
      34             : #include "Member.h"
      35             : #include "Optimizer.h"
      36             : 
      37             : namespace PLMD {
      38             : namespace maze {
      39             : 
      40             : /**
      41             :  * @class Memetic Memetic.h "maze/Memetic.h"
      42             :  *
      43             :  * @brief Memetic algorithms for the optimization of the loss function.
      44             :  */
      45             : class Memetic: public Optimizer {
      46             : public:
      47             :   /**
      48             :    * PLMD constructor.
      49             :    *
      50             :    * @param[in] ao PLMD::ActionOptions&.
      51             :    */
      52             :   explicit Memetic(const ActionOptions& ao);
      53             : 
      54             :   /**
      55             :    * Destructor required for deriving classes.
      56             :    */
      57             :   ~Memetic();
      58             : 
      59             :   /**
      60             :    * Registers PLMD keywords.
      61             :    *
      62             :    * @param[in] keys Keywords.
      63             :    */
      64             :   static void registerKeywords(Keywords& keys);
      65             : 
      66             :   /**
      67             :    * Each class deriving from Optimizer needs to override this function.
      68             :    */
      69             :   void optimize() override;
      70             : 
      71             : private:
      72             :   /**
      73             :    * Create a set of translations relative to the ligand, each translation
      74             :    * encodes a probable biasing direction.
      75             :    */
      76             :   void initialize_members();
      77             : 
      78             :   /**
      79             :    * Score each translation by the loss function.
      80             :    */
      81             :   void score_members();
      82             : 
      83             :   /**
      84             :    * Calculate the mean score.
      85             :    */
      86             :   double score_mean();
      87             : 
      88             :   /**
      89             :    * Sort the population using heaps, required for finding a minimum of the loss
      90             :    * function.
      91             :    */
      92             :   void sort_members();
      93             : 
      94             :   /**
      95             :    * Encode a ligand conformation.
      96             :    */
      97             :   Vector create_coding();
      98             : 
      99             :   /**
     100             :    * Check if the vector length is out of bounds.
     101             :    *
     102             :    * @param[in] v Vector length.
     103             :    */
     104             :   bool out_of_bounds(double v);
     105             : 
     106             :   /**
     107             :    * Score a single member.
     108             :    *
     109             :    * @param[in] v Member's translation.
     110             :    */
     111             :   double score_member(const Vector& v);
     112             : 
     113             :   /**
     114             :    * Print a status.
     115             :    */
     116             :   void print_status() const;
     117             : 
     118             :   /**
     119             :    * Select a new population using the roulette selection.
     120             :    */
     121             :   void selection_roulette();
     122             : 
     123             :   /**
     124             :    * Perform mating in the population.
     125             :    *
     126             :    * @param[in,out] members Population.
     127             :    */
     128             :   void mating(std::vector<Member>& members);
     129             : 
     130             :   /**
     131             :    * Mate two members.
     132             :    *
     133             :    * @param[in,out] m1 1st member.
     134             :    * @param[in,out] m2 2nd member.
     135             :    */
     136             :   void crossover(Member& m1, Member& m2);
     137             : 
     138             :   /**
     139             :    * Mutate a member.
     140             :    *
     141             :    * @param[in,out] m Member.
     142             :    */
     143             :   void mutation(Member& m);
     144             : 
     145             :   /**
     146             :    * Mutate the population.
     147             :    *
     148             :    * @param[in,out] members Population.
     149             :    */
     150             :   void mutation(std::vector<Member>& members);
     151             : 
     152             : protected:
     153             :   /**
     154             :    * Local searches to improve global solutions.
     155             :    */
     156             : 
     157             :   /**
     158             :    * Stochastic hill climbing.
     159             :    *
     160             :    * Neighbors with better or equal cost should be accepted, allowing the
     161             :    * technique to navigate across plateaus in the response surface.
     162             :    *
     163             :    * @param[in,out] m Member.
     164             :    * @param[in] params None.
     165             :    */
     166             :   void stochastic_hill_climbing(
     167             :     Member& m,
     168             :     /* none */ const std::vector<double>& params = {}
     169             :   );
     170             : 
     171             :   /**
     172             :    * Random-restart hill climbing.
     173             :    *
     174             :    * The algorithm can be restarted and repeated a number of  times after it
     175             :    * converges to provide an improved result.
     176             :    *
     177             :    * @param[in,out] m Member.
     178             :    * @param[in] params Number of restarts.
     179             :    */
     180             :   void random_restart_hill_climbing(
     181             :     Member& m,
     182             :     /* n_restarts */ const std::vector<double>& params = {10}
     183             :   );
     184             : 
     185             :   /**
     186             :    * Solis-Wets random walk.
     187             :    *
     188             :    * Adaptive random search algorithm was designed to address the limitations of
     189             :    * the fixed step size. The strategy for adaptive random search is to
     190             :    * continually approximate the optimal step size required to reach the global
     191             :    * optimum in the search space. This is achieved by trialling and adopting
     192             :    * smaller or larger step sizes only if they result in an improvement in the
     193             :    * search performance.
     194             :    *
     195             :    * Very large step sizes are trialled with a much lower frequency. This
     196             :    * strategy of preferring large moves is intended to allow the technique to
     197             :    * escape local optima. Smaller step sizes are adopted if no improvement is
     198             :    * made for an extended period.
     199             :    *
     200             :    * @param[in,out] m Member.
     201             :    * @param[in] params
     202             :    */
     203             :   void adaptive_random_search(
     204             :     Member& m,
     205             :     /* */ const std::vector<double>& params = {1.0, 1.e-5, 2.0, 2.0, 3.0, 3.0}
     206             :   );
     207             : 
     208             :   /**
     209             :    * Luus–Jaakola heuristics.
     210             :    *
     211             :    * @param[in,out] m Member.
     212             :    * @param[in] params Bounds.
     213             :    */
     214             :   void luus_jaakola(
     215             :     Member& m,
     216             :     /* bounds */ const std::vector<double>& params
     217             :   );
     218             : 
     219             :   /**
     220             :    * Local annealing.
     221             :    *
     222             :    * @param[in,out] m Member.
     223             :    * @param[in] params T, alpha.
     224             :    */
     225             :   void annealing(
     226             :     Member& m,
     227             :     /* T, alpha */const std::vector<double>& params = {300.0, 0.95}
     228             :   );
     229             : 
     230             :   /**
     231             :    * Apply local search to members.
     232             :    *
     233             :    * @param[in,out] members Population.
     234             :    */
     235             :   void local_search(std::vector<Member>& members);
     236             : 
     237             : protected:
     238             :   /**
     239             :    * Return an optimal biasing direction.
     240             :    */
     241             :   Vector solve();
     242             : 
     243             : public:
     244             :   /**
     245             :    * Setters and getters.
     246             :    */
     247             : 
     248             :   unsigned int get_capacity() const;
     249             :   void set_capacity(unsigned int);
     250             : 
     251             :   unsigned int get_coding_len() const;
     252             :   void set_coding_len(unsigned int);
     253             : 
     254             :   unsigned int get_n_local_iterations() const;
     255             :   void set_n_local_iterations(unsigned int);
     256             : 
     257             :   unsigned int get_n_global_iterations() const;
     258             :   void set_n_global_iterations(unsigned int);
     259             : 
     260             :   double get_mutation_rate() const;
     261             :   void set_mutation_rate(double);
     262             : 
     263             :   double get_mating_rate() const;
     264             :   void set_mating_rate(double);
     265             : 
     266             :   double get_cauchy_mean() const;
     267             :   void set_cauchy_mean(double);
     268             : 
     269             :   double get_cauchy_spread() const;
     270             :   void set_cauchy_spread(double);
     271             : 
     272             :   bool is_local_search_on() const;
     273             :   void local_search_on();
     274             :   void local_search_off();
     275             : 
     276             :   double get_local_search_rate() const;
     277             :   void set_local_search_rate(double);
     278             : 
     279             :   std::string get_local_search_type() const;
     280             :   void set_local_search_type(const std::string&);
     281             : 
     282             : protected:
     283             :   //! Population
     284             :   std::vector<Member> members_;
     285             : 
     286             :   //! Bound
     287             :   double bound_;
     288             : 
     289             :   //! Scores
     290             :   double score_worst_;
     291             :   double score_best_;
     292             :   Member member_best_;
     293             : 
     294             :   //! If a local search is performed
     295             :   bool adaptation_;
     296             : 
     297             : protected:
     298             :   //! Size of population
     299             :   unsigned int capacity_;
     300             :   //! Length of coding
     301             :   unsigned int coding_len_;
     302             : 
     303             :   //! Number of local search iterations
     304             :   unsigned int n_local_iterations_;
     305             :   //! Number of global search iterations, doomsday
     306             :   unsigned int n_global_iterations_;
     307             : 
     308             :   //! Probability of mutation
     309             :   double mutation_rate_;
     310             :   //! Probability of mating
     311             :   double mating_rate_;
     312             : 
     313             :   //! Mean and spread of cauchy sampler
     314             :   double cauchy_mean_alpha_;
     315             :   double cauchy_mean_beta_;
     316             : 
     317             :   //! If local search is employed in sampling
     318             :   bool local_search_on_;
     319             :   //! Rate of local mutation
     320             :   double local_search_rate_;
     321             :   //! Type of local search, stochastic_hill_climbing or adaptive_random_search
     322             :   std::string local_search_type_;
     323             : };
     324             : 
     325           6 : void Memetic::initialize_members() {
     326           6 :   members_.clear();
     327           6 :   members_.resize(capacity_);
     328             : 
     329          42 :   for (size_t i = 0; i < capacity_; ++i) {
     330          36 :     Member m{};
     331             : 
     332          36 :     m.score=0;
     333          36 :     m.translation=create_coding();
     334             : 
     335          36 :     members_.at(i) = m;
     336             :   }
     337           6 : }
     338             : 
     339          30 : void Memetic::score_members() {
     340         210 :   for (size_t i = 0; i < members_.size(); ++i) {
     341         180 :     double s = score_member(members_[i].translation);
     342         180 :     members_[i].score=s;
     343             :   }
     344          30 : }
     345             : 
     346          30 : void Memetic::sort_members() {
     347          30 :   std::make_heap(
     348             :     members_.begin(),
     349             :     members_.end(),
     350             :     compare
     351             :   );
     352             : 
     353          30 :   std::sort_heap(
     354             :     members_.begin(),
     355             :     members_.end(),
     356             :     compare
     357             :   );
     358             : 
     359          30 :   member_best_ = members_[capacity_ - 1];
     360          30 :   score_best_ = members_[capacity_ - 1].score;
     361          30 :   score_worst_ = members_[0].score;
     362          30 : }
     363             : 
     364           0 : double Memetic::score_mean() {
     365           0 :   auto acc = [](double s, const Member& m) { return s + m.score; };
     366             : 
     367             :   return std::accumulate(
     368             :            members_.begin(),
     369             :            members_.end(),
     370             :            0.0,
     371           0 :            acc) / capacity_;
     372             : }
     373             : 
     374          30 : void Memetic::selection_roulette() {
     375          30 :   std::vector<Member> sel(members_);
     376          30 :   std::vector<double> rel_scores(capacity_, 0.0);
     377             : 
     378         210 :   for (std::size_t i = 0; i < capacity_; ++i) {
     379         180 :     double r = 1.0 / (members_[i].score + 0.01);
     380         180 :     rel_scores.at(i) = r;
     381             :   }
     382             : 
     383          30 :   std::vector<double> cum_sum(capacity_, 0.0);
     384          30 :   std::partial_sum(
     385             :     rel_scores.begin(),
     386             :     rel_scores.end(),
     387             :     cum_sum.begin(),
     388             :     std::plus<double>()
     389             :   );
     390             : 
     391          30 :   double sum = cum_sum.back();
     392             :   members_.clear();
     393          30 :   members_.resize(capacity_);
     394             :   int chosen = -1;
     395             : 
     396         210 :   for (size_t j = 0; j < capacity_; ++j) {
     397             :     double probability=rnd::next_double(sum);
     398         642 :     for (size_t i = 0; i < cum_sum.size(); ++i) {
     399         642 :       if (cum_sum[i] > probability) {
     400         180 :         chosen = i;
     401             : 
     402         360 :         members_.at(j).score = sel.at(chosen).score;
     403         180 :         members_.at(j).translation = sel.at(chosen).translation;
     404             : 
     405         180 :         break;
     406             :       }
     407             :     }
     408             :   }
     409          30 : }
     410             : 
     411           4 : void Memetic::crossover(Member& s1, Member& s2) {
     412           4 :   size_t i = rnd::next_int(1, coding_len_ - 1);
     413             : 
     414           4 :   Member z1(s1);
     415           4 :   Member z2(s2);
     416             : 
     417          12 :   for (size_t j = i; j < coding_len_; ++j) {
     418           8 :     z1.translation[j] = s2.translation[j];
     419           8 :     z2.translation[j] = s1.translation[j];
     420             :   }
     421             : 
     422           4 :   if (!out_of_bounds(z1.translation.modulo()) && !out_of_bounds(z2.translation.modulo())) {
     423           4 :     s1 = z1;
     424           4 :     s2 = z2;
     425             :   }
     426           4 : }
     427             : 
     428          94 : void Memetic::mutation(Member& m) {
     429          94 :   int which = rnd::next_int(coding_len_);
     430          94 :   double v = rnd::next_cauchy(cauchy_mean_alpha_, cauchy_mean_beta_);
     431          94 :   m.translation[which] += v;
     432          94 :   if (out_of_bounds(m.translation.modulo())) {
     433          27 :     m.translation[which] -= v;
     434             :   }
     435          94 : }
     436             : 
     437          30 : void Memetic::mutation(std::vector<Member>& m) {
     438         210 :   for (std::vector<Member>::iterator it = m.begin(), end = m.end(); it != end; ++it) {
     439         180 :     double r = rnd::next_double();
     440         180 :     if (r < mutation_rate_) {
     441           4 :       mutation(*it);
     442             :     }
     443             :   }
     444          30 : }
     445             : 
     446           9 : void Memetic::stochastic_hill_climbing(
     447             :   Member& m,
     448             :   const std::vector<double>& params)
     449             : {
     450          99 :   for (std::size_t i = 0; i < n_local_iterations_; ++i) {
     451          90 :     Member n;
     452          90 :     n.translation = m.translation;
     453          90 :     mutation(n);
     454          90 :     double score_n = score_member(n.translation);
     455             : 
     456          90 :     if (m.score > score_n) {
     457          48 :       m.translation = n.translation;
     458             :     }
     459             :   }
     460           9 : }
     461             : 
     462           0 : void Memetic::random_restart_hill_climbing(
     463             :   Member& m,
     464             :   const std::vector<double>& params)
     465             : {
     466           0 :   unsigned int n_restarts = static_cast<int>(params[0]);
     467           0 :   std::vector<Member> s(n_restarts);
     468             :   unsigned int ndx = 0;
     469           0 :   double min = m.score;
     470             : 
     471           0 :   for (std::size_t r = 0; r < n_restarts; ++r) {
     472           0 :     Member n = m;
     473           0 :     stochastic_hill_climbing(n);
     474           0 :     s[r] = n;
     475             : 
     476           0 :     if (min > n.score) {
     477             :       min = n.score;
     478           0 :       ndx = r;
     479             :     }
     480             :   }
     481             : 
     482           0 :   m = s[ndx];
     483           0 : }
     484             : 
     485           0 : void Memetic::annealing(
     486             :   Member& m,
     487             :   const std::vector<double>& params)
     488             : {
     489           0 :   double T = params[0];
     490           0 :   double alpha = params[1];
     491             : 
     492           0 :   for (std::size_t i = 0; i < n_local_iterations_; ++i) {
     493           0 :     Member n = m;
     494           0 :     mutation(n);
     495           0 :     double score_n = score_member(n.translation);
     496             : 
     497             :     double probability = std::min(
     498           0 :                            1.0,
     499           0 :                            std::exp(-(score_n - m.score) / T)
     500           0 :                          );
     501             : 
     502           0 :     double r = rnd::next_double();
     503             : 
     504           0 :     if (r < probability) {
     505           0 :       m = n;
     506             :     }
     507             : 
     508           0 :     T *= alpha;
     509             :   }
     510           0 : }
     511             : 
     512           0 : void Memetic::luus_jaakola(
     513             :   Member& m,
     514             :   const std::vector<double>& params)
     515             : {
     516             :   /* TODO */
     517           0 : }
     518             : 
     519           0 : void Memetic::adaptive_random_search(
     520             :   Member& m,
     521             :   const std::vector<double>& params)
     522             : {
     523           0 :   double rho_start = params[0];
     524           0 :   double rho_lower_bound = params[1];
     525           0 :   double ex = params[2];
     526           0 :   double ct = params[3];
     527           0 :   int s_ex = static_cast<int>(params[4]);
     528           0 :   int f_ct = static_cast<int>(params[5]);
     529             : 
     530             :   unsigned int k = 0;
     531           0 :   Vector xk = m.translation;
     532             :   int ns = 0;
     533             :   int nf = 0;
     534           0 :   Vector bk;
     535           0 :   bk.zero();
     536             :   double rho_k = rho_start;
     537             : 
     538           0 :   while (rho_k > rho_lower_bound && k < n_local_iterations_) {
     539           0 :     if (ns >= s_ex) {
     540           0 :       rho_k *= ex;
     541             :     }
     542           0 :     else if (nf >= f_ct) {
     543           0 :       rho_k *= ct;
     544             :     }
     545             : 
     546           0 :     std::vector<double> chiv = rnd::next_double(-rho_k, rho_k, 3);
     547           0 :     Vector chi = tls::vector2Vector(chiv);
     548           0 :     Vector tmp;
     549             : 
     550           0 :     for (unsigned int i = 0; i < 3; ++i) {
     551           0 :       tmp[i] = 2.0 * (xk[i] - chi[i]);
     552             :     }
     553             : 
     554           0 :     double score_chi = score_member(chi);
     555           0 :     double score_xk = score_member(xk);
     556           0 :     double score_tmp = score_member(tmp);
     557             : 
     558           0 :     if (score_chi < score_xk) {
     559           0 :       ns++;
     560             :       nf = 0;
     561             : 
     562           0 :       for (unsigned int i = 0; i < 3; i++) {
     563           0 :         bk[i] = 0.2 * bk[i] + 0.4 * (chi[i] - xk[i]);
     564           0 :         xk[i] = chi[i];
     565             :       }
     566             :     }
     567           0 :     else if (score_tmp < score_xk && score_xk <= score_chi) {
     568           0 :       ns++;
     569             :       nf = 0;
     570             : 
     571           0 :       for (unsigned int i = 0; i < 3; i++) {
     572           0 :         bk[i] = bk[i] - 0.4 * (chi[i] - xk[i]);
     573           0 :         xk[i] = 2.0 * xk[i] - chi[i];
     574             :       }
     575             :     }
     576             :     else {
     577             :       ns = 0;
     578           0 :       nf++;
     579             : 
     580           0 :       for (unsigned int i = 0; i < 3; i++) {
     581           0 :         bk[i] = 0.5 * bk[i];
     582             :       }
     583             :     }
     584             : 
     585           0 :     k++;
     586             :   }
     587             : 
     588           0 :   m.translation = xk;
     589           0 : }
     590             : 
     591          30 : void Memetic::local_search(std::vector<Member>& m) {
     592          30 :   adaptation_ = true;
     593             : 
     594          30 :   if (local_search_on_) {
     595         105 :     for (std::size_t i = 0; i < capacity_; ++i) {
     596          90 :       double probability = rnd::next_double();
     597             : 
     598          90 :       if (probability < local_search_rate_) {
     599           9 :         if (local_search_type_ == "stochastic_hill_climbing")
     600          18 :           stochastic_hill_climbing(m[i]);
     601           0 :         else if (local_search_type_ == "adaptive_random_search")
     602           0 :           adaptive_random_search(m[i]);
     603           0 :         else if (local_search_type_ == "random_restart_hill_climbing")
     604           0 :           random_restart_hill_climbing(m[i]);
     605             :       }
     606             :     }
     607             :   }
     608             : 
     609          30 :   adaptation_ = false;
     610          30 : }
     611             : 
     612          30 : void Memetic::mating(std::vector<Member>& m) {
     613             :   std::vector<Member> offspring;
     614             : 
     615         120 :   while (m.size() != 0) {
     616          90 :     int j = rnd::next_int(m.size());
     617          90 :     int i = rnd::next_int(m.size());
     618             : 
     619         140 :     while (i == j) {
     620          50 :       j=rnd::next_int(m.size());
     621             :     }
     622             : 
     623          90 :     Member m1 = m[i];
     624          90 :     Member m2 = m[j];
     625             : 
     626          90 :     if (i > j) {
     627             :       m.erase(m.begin() + i);
     628             :       m.erase(m.begin() + j);
     629             :     }
     630          41 :     else if (j > i) {
     631             :       m.erase(m.begin() + j);
     632             :       m.erase(m.begin() + i);
     633             :     }
     634             : 
     635          90 :     double probability = rnd::next_double();
     636          90 :     if (probability < mating_rate_) {
     637           4 :       crossover(m1, m2);
     638             :     }
     639             : 
     640          90 :     offspring.push_back(m1);
     641          90 :     offspring.push_back(m2);
     642             :   }
     643             : 
     644          30 :   m = offspring;
     645             :   offspring.clear();
     646          30 : }
     647             : 
     648          36 : Vector Memetic::create_coding() {
     649          36 :   double s = sampling_radius();
     650             :   double r = rnd::next_double(s);
     651             : 
     652          36 :   return rnd::next_plmd_vector(r);
     653             : }
     654             : 
     655         102 : bool Memetic::out_of_bounds(double v) {
     656         102 :   double s = sampling_radius();
     657             : 
     658         102 :   return v > s;
     659             : }
     660             : 
     661         270 : double Memetic::score_member(const Vector& coding) {
     662             :   double action = 0;
     663         270 :   Vector distance;
     664         270 :   const unsigned nl_size = neighbor_list_->size();
     665         270 :   Vector dev = coding;
     666             : 
     667         270 :   #pragma omp parallel num_threads(get_n_threads_openmp())
     668             :   {
     669             :     #pragma omp for reduction(+:action)
     670             :     for (unsigned int i = 0; i < nl_size; i++) {
     671             :       unsigned i0 = neighbor_list_->getClosePair(i).first;
     672             :       unsigned i1 = neighbor_list_->getClosePair(i).second;
     673             : 
     674             :       if (getAbsoluteIndex(i0) == getAbsoluteIndex(i1)) {
     675             :         continue;
     676             :       }
     677             : 
     678             :       if (pbc_) {
     679             :         distance = pbcDistance(getPosition(i0) + dev, getPosition(i1));
     680             :       }
     681             :       else {
     682             :         distance = delta(getPosition(i0) + dev, getPosition(i1));
     683             :       }
     684             : 
     685             :       action += pairing(distance.modulo());
     686             :     }
     687             :   }
     688             : 
     689         270 :   return action;
     690             : }
     691             : 
     692           0 : void Memetic::print_status() const {
     693           0 :   log.printf("Lowest score: %f \n", score_best_);
     694           0 : }
     695             : 
     696           6 : Vector Memetic::solve() {
     697           6 :   initialize_members();
     698             : 
     699             :   size_t epoch = 0;
     700          36 :   while (epoch < n_global_iterations_) {
     701          30 :     score_members();
     702             : 
     703          30 :     selection_roulette();
     704          30 :     mating(members_);
     705          30 :     mutation(members_);
     706          30 :     local_search(members_);
     707             : 
     708          30 :     sort_members();
     709             : 
     710          30 :     epoch++;
     711             :   }
     712             : 
     713           6 :   return member_best_.translation / member_best_.translation.modulo();
     714             : }
     715             : 
     716             : inline unsigned int Memetic::get_capacity() const {
     717             :   return capacity_;
     718             : }
     719             : 
     720             : inline void Memetic::set_capacity(unsigned int capacity) {
     721             :   capacity_ = capacity;
     722             : }
     723             : 
     724             : inline unsigned int Memetic::get_coding_len() const {
     725             :   return coding_len_;
     726             : }
     727             : 
     728             : inline void Memetic::set_coding_len(unsigned int coding_len) {
     729             :   coding_len_ = coding_len;
     730             : }
     731             : 
     732             : inline unsigned int Memetic::get_n_global_iterations() const {
     733             :   return n_global_iterations_;
     734             : }
     735             : 
     736             : inline void Memetic::set_n_global_iterations(unsigned int n_global_iterations) {
     737           2 :   n_global_iterations_ = n_global_iterations;
     738             : }
     739             : 
     740             : inline unsigned int Memetic::get_n_local_iterations() const {
     741             :   return n_local_iterations_;
     742             : }
     743             : 
     744             : inline void Memetic::set_n_local_iterations(unsigned int n_local_iterations) {
     745             :   n_local_iterations_ = n_local_iterations;
     746             : }
     747             : 
     748             : inline double Memetic::get_mating_rate() const {
     749             :   return mating_rate_;
     750             : }
     751             : 
     752             : inline void Memetic::set_mating_rate(double mating_rate) {
     753             :   mating_rate_ = mating_rate;
     754             : }
     755             : 
     756             : inline double Memetic::get_mutation_rate() const {
     757             :   return mutation_rate_;
     758             : }
     759             : 
     760             : inline void Memetic::set_mutation_rate(double mutation_rate) {
     761             :   mutation_rate_ = mutation_rate;
     762             : }
     763             : 
     764             : inline double Memetic::get_cauchy_mean() const {
     765             :   return cauchy_mean_alpha_;
     766             : }
     767             : 
     768             : inline void Memetic::set_cauchy_mean(double cauchy_mean_alpha) {
     769             :   cauchy_mean_alpha_ = cauchy_mean_alpha;
     770             : }
     771             : 
     772             : inline double Memetic::get_cauchy_spread() const {
     773             :   return cauchy_mean_beta_;
     774             : }
     775             : 
     776             : inline void Memetic::set_cauchy_spread(double cauchy_mean_beta) {
     777             :   cauchy_mean_beta_ = cauchy_mean_beta;
     778             : }
     779             : 
     780             : inline bool Memetic::is_local_search_on() const {
     781             :   return local_search_on_;
     782             : }
     783             : 
     784             : inline void Memetic::local_search_on() {
     785             :   local_search_on_ = true;
     786             : }
     787             : 
     788             : inline void Memetic::local_search_off() {
     789             :   local_search_on_ = false;
     790             : }
     791             : 
     792             : inline double Memetic::get_local_search_rate() const {
     793             :   return local_search_rate_;
     794             : }
     795             : 
     796             : inline void Memetic::set_local_search_rate(double local_search_rate) {
     797             :   local_search_rate_ = local_search_rate;
     798             : }
     799             : 
     800             : inline std::string Memetic::get_local_search_type() const {
     801             :   return local_search_type_;
     802             : }
     803             : 
     804             : inline void Memetic::set_local_search_type(const std::string& local_search_type) {
     805             :   local_search_type_ = local_search_type;
     806             : }
     807             : 
     808             : } // namespace maze
     809             : } // namespace PLMD
     810             : 
     811             : #endif // __PLUMED_maze_Memetic_h

Generated by: LCOV version 1.15