RockyML  0.0.1
A High-Performance Scientific Computing Framework
eda.h
1 /*
2  Copyright (C) 2022 Amirabbas Asadi , All Rights Reserved
3  distributed under Apache-2.0 license
4 */
5 #ifndef ROCKY_ZAGROS_EDA_STRATEGY
6 #define ROCKY_ZAGROS_EDA_STRATEGY
7 
8 
9 #include <rocky/zagros/strategies/strategy.h>
10 
11 #include <Eigen/Core>
12 #include <Eigen/Cholesky>
13 
14 
15 namespace rocky{
16 namespace zagros{
17 
22 template<typename T_e, int T_dim>
23 class eda_strategy: public basic_strategy<T_e, T_dim>{};
24 
29 template<typename T_e, int T_dim>
30 class eda_mutivariate_normal: public eda_strategy<T_e, T_dim>{
31 protected:
32  // system
33  system<T_e>* problem_;
34  // main container
35  basic_scontainer<T_e, T_dim>* target_container_;
36  // container holding the generated candidates
37  basic_scontainer<T_e, T_dim>* candidates_container_;
38  // number of generated candidates
39  std::vector<T_e> top_particles_mem_;
40  // a placeholder for top-k solutions
41  std::vector<int> solution_ind_;
42  // covariance matrix
43  std::vector<T_e> cov_mem_;
44  // mean vector
45  std::vector<T_e> mean_mem_;
46  // sample size for computing covariance matrix
47  int sample_size_;
48  // number of generated candidates in each step
49  int n_candidates_;
50 
51 public:
52  eda_mutivariate_normal(system<T_e>* problem, basic_scontainer<T_e, T_dim>* tgt_container, basic_scontainer<T_e, T_dim>* cnd_container, int sample_size){
53  this->problem_ = problem;
54  this->target_container_ = tgt_container;
55  this->candidates_container_ = cnd_container;
56  this->sample_size_ = sample_size;
57  this->n_candidates_ = cnd_container->n_particles();
58  top_particles_mem_.resize(sample_size * T_dim);
59  solution_ind_.resize(sample_size);
60  cov_mem_.resize(T_dim * T_dim);
61  mean_mem_.resize(T_dim);
62  }
63  void sample_std_normal(T_e* vec){
64  static std::normal_distribution<T_e> dist(0.0, 1.0);
65  tbb::parallel_for(0, T_dim, [&](auto i){
66  vec[i] = dist(rocky::utils::random::prng());
67  });
68  }
69  virtual void apply(){
70  // find top k solutions
71  target_container_->best_k(solution_ind_.data(), sample_size_);
72  // copy the best soluions
73  T_e* top_particles_ptr = top_particles_mem_.data();
74 
75  tbb::parallel_for(0, sample_size_, [&](int p){
76  std::copy(this->target_container_->particle(this->solution_ind_[p]),
77  this->target_container_->particle(this->solution_ind_[p]) + T_dim,
78  top_particles_ptr + p * T_dim);
79  });
80  // estimate the mean and covariance
81  Eigen::Map<Eigen::Matrix<T_e, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>> top_particles_mat(top_particles_mem_.data(), sample_size_, T_dim);
82  Eigen::Map<Eigen::Matrix<T_e, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>> cov_mat(cov_mem_.data(), T_dim, T_dim);
83  Eigen::Map<Eigen::Matrix<T_e, 1, T_dim, Eigen::RowMajor>> mean_mat(mean_mem_.data());
84 
85  mean_mat = top_particles_mat.colwise().mean();
86  top_particles_mat.rowwise() -= mean_mat;
87  cov_mat = (top_particles_mat.adjoint() * top_particles_mat) / static_cast<T_e>(sample_size_-1);
88  // cholesky decomposition
89  Eigen::LLT<Eigen::Matrix<T_e, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>> llt(cov_mat);
90  // generate samples from mvn
91  tbb::parallel_for(0, sample_size_, [&](auto p){
92  Eigen::Map<Eigen::Matrix<T_e, 1, T_dim, Eigen::RowMajor>> sample_mat(this->candidates_container_->particle(p));
93  sample_std_normal(this->candidates_container_->particle(p));
94  sample_mat = (llt.matrixL() * sample_mat.transpose()).transpose();
95  sample_mat.rowwise() += mean_mat;
96  });
97  // evaluate generated candidates
98  this->candidates_container_->evaluate_and_update(this->problem_);
99  // replace the best candidates in the target container
100  this->target_container_->replace_with(this->candidates_container_);
101  }
102 };
103 
104 
105 
106 }; // end of zagros
107 }; // end of rocky
108 #endif
rocky::zagros::basic_scontainer::best_k
void best_k(int *indices, int k)
find top-k solutions and fill the indices
Definition: scontainer.h:236
rocky::zagros::basic_scontainer::replace_with
void replace_with(basic_scontainer< T_e, T_dim > *cnt)
replace the best values from another container
Definition: scontainer.h:266
rocky::zagros::eda_strategy
Base class for estimation of distribution algorithms.
Definition: eda.h:23
rocky::zagros::basic_scontainer
a data container representing a scontainer
Definition: scontainer.h:31
rocky::zagros::system
Definition: system.h:20
rocky::zagros::basic_scontainer::evaluate_and_update
void evaluate_and_update(system< T_e > *problem, int rng_start, int rng_end)
evaluate and update the particles within a range
Definition: scontainer.h:205
rocky::zagros::basic_strategy
Interface for all strategies.
Definition: strategy.h:31
rocky::zagros::basic_scontainer::particle
T_e * particle(int p)
get the starting address of a specific particle
Definition: scontainer.h:71
rocky::zagros::eda_mutivariate_normal
estimating the distribution of solutions using eda
Definition: eda.h:30