OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
main.cpp
1 
144 
146 // This example need EIGEN, if we do not have NOP the full example
147 
148 #include "config.h"
149 
150 #ifndef HAVE_EIGEN
151 
152 int main(int argc, char* argv[])
153 {
154  return 0;
155 }
156 
157 #else
158 
159 
160 #define EIGEN_USE_LAPACKE
161 #include "Vector/vector_dist.hpp"
162 #include "DMatrix/EMatrix.hpp"
163 #include <Eigen/Eigenvalues>
164 #include <Eigen/Jacobi>
165 #include <limits>
166 #include "Vector/vector_dist.hpp"
167 #include <f15_cec_fun.hpp>
168 #include <boost/math/special_functions/sign.hpp>
169 
171 
173 
174 // PARAMETERS
175 constexpr int dim = 10;
176 // when you set dim set also lambda to to 4+std::floor(3*log(dim))
177 constexpr int lambda = 7;
178 constexpr int mu = lambda/2;
179 double psoWeight = 0.7;
180 // number of cma-step before pso step
181 int N_pso = 200;
182 double stopTolX = 2e-11;
183 double stopTolUpX = 2000.0;
184 int restart_cma = 1;
185 size_t max_fun_eval = 30000000;
186 constexpr int hist_size = 21;
187 
188 // Convenient global variables (Their value is set after)
189 double mu_eff = 1.0;
190 double cs = 1.0;
191 double cc = 1.0;
192 double ccov = 1.0;
193 double chiN;
194 double d_amps = 1.0;
195 double stop_fitness = 1.0;
196 int eigeneval = 0;
197 double t_c = 0.1;
198 double b = 0.1;
199 
201 
203 
205 
206 constexpr int sigma = 0;
207 constexpr int Cov_m = 1;
208 constexpr int B = 2;
209 constexpr int D = 3;
210 constexpr int Zeta = 4;
211 constexpr int path_s = 5;
212 constexpr int path_c = 6;
213 constexpr int ord = 7;
214 constexpr int stop = 8;
215 constexpr int fithist = 9;
216 constexpr int weight = 10;
217 constexpr int validfit = 11;
218 constexpr int xold = 12;
219 constexpr int last_restart = 13;
220 constexpr int iniphase = 14;
221 constexpr int xmean_st = 15;
222 constexpr int meanz_st = 16;
223 
224 typedef vector_dist<dim,double, aggregate<double,
225  EMatrixXd,
226  EMatrixXd,
227  Eigen::DiagonalMatrix<double,Eigen::Dynamic>,
228  EVectorXd[lambda],
229  EVectorXd,
230  EVectorXd,
231  int[lambda],
232  int,
233  double [hist_size],
234  double [dim],
235  double,
236  EVectorXd,
237  int,
238  bool,
239  EVectorXd,
240  EVectorXd> > particle_type;
241 
243 
258 
260 double generateGaussianNoise(double mu, double sigma)
261 {
262  static const double epsilon = std::numeric_limits<double>::min();
263  static const double two_pi = 2.0*3.14159265358979323846;
264 
265  thread_local double z1;
266  thread_local double generate;
267  generate = !generate;
268 
269  if (!generate)
270  {return z1 * sigma + mu;}
271 
272  double u1, u2;
273  do
274  {
275  u1 = rand() * (1.0 / RAND_MAX);
276  u2 = rand() * (1.0 / RAND_MAX);
277  }
278  while ( u1 <= epsilon );
279 
280  double z0;
281  z0 = sqrt(-2.0 * log(u2)) * cos(two_pi * u1);
282  z1 = sqrt(-2.0 * log(u2)) * sin(two_pi * u1);
283  return z0 * sigma + mu;
284 }
285 
286 template<unsigned int dim>
287 EVectorXd generateGaussianVector()
288 {
289  EVectorXd tmp;
290  tmp.resize(dim);
291 
292  for (size_t i = 0 ; i < dim ; i++)
293  {
294  tmp(i) = generateGaussianNoise(0,1);
295  }
296 
297  return tmp;
298 }
299 
301 
302 template<unsigned int dim>
303 void fill_vector(double (& f)[dim], EVectorXd & ev)
304 {
305  for (size_t i = 0 ; i < dim ; i++)
306  {ev(i) = f[i];}
307 }
308 
309 void fill_vector(const double * f, EVectorXd & ev)
310 {
311  for (size_t i = 0 ; i < ev.size() ; i++)
312  {ev(i) = f[i];}
313 }
314 
315 struct fun_index
316 {
317  double f;
318  int id;
319 
320  bool operator<(const fun_index & tmp) const
321  {
322  return f < tmp.f;
323  }
324 };
325 
326 double wm[mu];
327 
328 void init_weight()
329 {
330  for (size_t i = 0 ; i < mu ; i++)
331  {wm[i] = log(double(mu)+1.0) - log(double(i)+1.0);}
332 
333  double tot = 0.0;
334 
335  for (size_t i = 0 ; i < mu ; i++)
336  {tot += wm[i];}
337 
338  double sum = 0.0;
339  double sum2 = 0.0;
340 
341  for (size_t i = 0 ; i < mu ; i++)
342  {
343  wm[i] /= tot;
344  sum += wm[i];
345  sum2 += wm[i]*wm[i];
346  }
347 
348  // also set mu_eff
349  mu_eff=sum*sum/sum2;
350 
351 }
352 
353 double weight_sample(int i)
354 {
355  return wm[i];
356 }
357 
370 
372 void create_rotmat(EVectorXd & S,EVectorXd & T, EMatrixXd & R)
373 {
374  EVectorXd S_work(dim);
375  EVectorXd T_work(dim);
376  EVectorXd S_sup(dim);
377  EVectorXd T_sup(dim);
378 
379  EMatrixXd R_tar(dim,dim);
380  EMatrixXd R_tmp(dim,dim);
381  EMatrixXd R_sup(dim,dim);
382  double G_S,G_C;
383  EMatrixXd S_tmp(2,2);
384  EMatrixXd T_tmp(2,2);
385  int p,q,i;
386 
387  S_work = S;
388  T_work = T;
389 
390  R.setIdentity();
391  R_tar = R;
392  R_tmp = R;
393 
394  for (p = dim - 2; p >= 0 ; p -= 1)
395  {
396 
397  for (q = dim - 1 ; q >= p+1 ; q-= 1)
398  {
399  T_tmp(0) = T_work(p);
400  T_tmp(1) = T_work(q);
401  S_tmp(0) = S_work(p);
402  S_tmp(1) = S_work(q);
403 
404  // Perform Givens Rotation on start vector
405 
406  Eigen::JacobiRotation<double> G;
407  double z;
408  G.makeGivens(S_tmp(0), S_tmp(1),&z);
409 
410  // Check direction of rotation
411  double sign = 1.0;
412  if (z < 0.0)
413  {sign = -1.0;}
414 
415  // Build a Rotation Matrix out of G_C and G_S
416  R_tmp.setIdentity();
417  R_tmp(p,p) = sign*G.c();
418  R_tmp(q,q) = sign*G.c();
419  R_tmp(p,q) = sign*-G.s();
420  R_tmp(q,p) = sign*G.s();
421 
422  // Rotate start vector and update R
423  // S_work = R_tmp*S_work
424 
425  S_work = R_tmp*S_work;
426  // R = R_tmp*R
427  R = R_tmp*R;
428 
429  // Perform Givens Rotation on target vector
430 
431  G.makeGivens(T_tmp(0), T_tmp(1),&z);
432 
433  sign = 1.0;
434  if (z < 0.0)
435  {sign = -1.0;}
436 
437  R_tmp.setIdentity();
438  R_tmp(p,p) = sign*G.c();
439  R_tmp(q,q) = sign*G.c();
440  R_tmp(p,q) = sign*-G.s();
441  R_tmp(q,p) = sign*G.s();
442 
443  // Rotate target vector and update R_tar
444 
445  T_work = R_tmp*T_work;
446  R_tar = R_tmp*R_tar;
447  }
448  }
449 
450  R = R_tar.transpose()*R;
451 
452  // Check the rotation
453 
454  EVectorXd Check(dim);
455  Check = R*S;
456 }
457 
459 
474 
476 void updatePso(openfpm::vector<double> & best_sol,
477  double sigma,
478  EVectorXd & xmean,
479  EVectorXd & xold,
480  EMatrixXd & B,
481  Eigen::DiagonalMatrix<double,Eigen::Dynamic> & D,
482  EMatrixXd & C_pso)
483 {
484  EVectorXd best_sol_ei(dim);
485 
486  double bias_weight = psoWeight;
487  fill_vector(&best_sol.get(0),best_sol_ei);
488  EVectorXd gb_vec = best_sol_ei-xmean;
489  double gb_vec_length = sqrt(gb_vec.transpose() * gb_vec);
490  EVectorXd b_main = B.col(dim-1);
491  EVectorXd bias(dim);
492  bias.setZero();
493 
494  // Rotation Matrix
495  EMatrixXd R(dim,dim);
496 
497  if (gb_vec_length > 0.0)
498  {
499  if(sigma < gb_vec_length)
500  {
501  if(sigma/gb_vec_length <= t_c*gb_vec_length)
502  {bias = 0.5*gb_vec;}
503  else
504  {bias = sigma*gb_vec/gb_vec_length;}
505  }
506  else
507  {bias.setZero();}
508  }
509 
510  xmean = xmean + bias;
511 
512  if (psoWeight < 1.0)
513  {
514  EMatrixXd B_rot(dim,dim);
515  Eigen::DiagonalMatrix<double,Eigen::Dynamic> D_square(dim);
516 
517  EVectorXd gb_vec_old = best_sol_ei - xold;
518  create_rotmat(b_main,gb_vec_old,R);
519  for (size_t i = 0 ; i < dim ; i++)
520  {B_rot.col(i) = R*B.col(i);}
521 
522  for (size_t i = 0 ; i < dim ; i++)
523  {D_square.diagonal()[i] = D.diagonal()[i] * D.diagonal()[i];}
524  C_pso = B_rot * D_square * B_rot.transpose();
525 
526  EMatrixXd trUp = C_pso.triangularView<Eigen::Upper>();
527  EMatrixXd trDw = C_pso.triangularView<Eigen::StrictlyUpper>();
528  C_pso = trUp + trDw.transpose();
529  }
530 }
531 
533 
550 
552 void broadcast_best_solution(particle_type & vd,
553  openfpm::vector<double> & best_sol,
554  double & best,
555  double best_sample,
556  openfpm::vector<double> & best_sample_sol)
557 {
558  best_sol.resize(dim);
559  auto & v_cl = create_vcluster();
560 
561  double best_old = best_sample;
562  v_cl.min(best_sample);
563  v_cl.execute();
564 
565  // The old solution remain the best
566  if (best < best_sample)
567  {return;}
568 
569  best = best_sample;
570 
571  size_t rank;
572  if (best_old == best_sample)
573  {
574  rank = v_cl.getProcessUnitID();
575 
576  // we own the minimum and we decide who broad cast
577  v_cl.min(rank);
578  v_cl.execute();
579 
580  if (rank == v_cl.getProcessUnitID())
581  {
582  for (size_t i = 0 ; i < dim ; i++)
583  {best_sol.get(i) = best_sample_sol.get(i);}
584  }
585  }
586  else
587  {
588  rank = std::numeric_limits<size_t>::max();
589 
590  // we do not own decide who broad cast
591  v_cl.min(rank);
592  v_cl.execute();
593  }
594 
595  // now we broad cast the best solution across processors
596 
597  v_cl.Bcast(best_sol,rank);
598  v_cl.execute();
599 }
600 
602 
622 
624 void cmaes_myprctile(openfpm::vector<fun_index> & f_obj, double (& perc)[2], double (& res)[2])
625 {
626  double sar[lambda];
627  double availablepercentiles[lambda];
628  int idx[hist_size];
629  int i,k;
630 
631  for (size_t i = 0 ; i < lambda ; i++)
632  {
633  availablepercentiles[i] = 0.0;
634  sar[i] = f_obj.get(i).f;
635  }
636  std::sort(&sar[0],&sar[lambda]);
637 
638  for (size_t i = 0 ; i < 2 ; i++)
639  {
640  if (perc[i] <= (100.0*0.5/lambda))
641  {res[i] = sar[0];}
642  else if (perc[i] >= (100.0*(lambda-0.5)/lambda) )
643  {res[i] = sar[lambda-1];}
644  else
645  {
646  for (size_t j = 0 ; j < lambda ; j++)
647  {availablepercentiles[j] = 100.0 * ((double(j)+1.0)-0.5) / lambda;}
648 
649  for (k = 0 ; k < lambda ; k++)
650  {if(availablepercentiles[k] >= perc[i]) {break;}}
651  k-=1;
652 
653  res[i] = sar[k] + (sar[k+1]-sar[k]) * (perc[i]
654  -availablepercentiles[k]) / (availablepercentiles[k+1] - availablepercentiles[k]);
655  }
656  }
657 }
658 
660 
661 double maxval(double (& buf)[hist_size], bool (& mask)[hist_size])
662 {
663  double max = 0.0;
664  for (size_t i = 0 ; i < hist_size ; i++)
665  {
666  if (buf[i] > max && mask[i] == true)
667  {max = buf[i];}
668  }
669 
670  return max;
671 }
672 
673 double minval(double (& buf)[hist_size], bool (& mask)[hist_size])
674 {
675  double min = std::numeric_limits<double>::max();
676  for (size_t i = 0 ; i < hist_size ; i++)
677  {
678  if (buf[i] < min && mask[i] == true)
679  {min = buf[i];}
680  }
681 
682  return min;
683 }
684 
686 
687 void cmaes_intobounds(EVectorXd & x, EVectorXd & xout,bool (& idx)[dim], bool & idx_any)
688 {
689  idx_any = false;
690  for (size_t i = 0; i < dim ; i++)
691  {
692  if(x(i) < -5.0)
693  {
694  xout(i) = -5.0;
695  idx[i] = true;
696  idx_any = true;
697  }
698  else if (x(i) > 5.0)
699  {
700  xout(i) = 5.0;
701  idx[i] = true;
702  idx_any = true;
703  }
704  else
705  {
706  xout(i) = x(i);
707  idx[i] = false;
708  }
709  }
710 }
711 
713 
715 
716 void cmaes_handlebounds(openfpm::vector<fun_index> & f_obj,
717  double sigma,
718  double & validfit,
719  EVectorXd (& arxvalid)[lambda],
720  EVectorXd (& arx)[lambda],
721  EMatrixXd & C,
722  EVectorXd & xmean,
723  EVectorXd & xold,
724  double (& weight)[dim],
725  double (& fithist)[hist_size],
726  bool & iniphase,
727  double & validfitval,
728  double mu_eff,
729  int step,
730  int last_restart)
731 {
732  double val[2];
733  double value;
734  double diag[dim];
735  double meandiag;
736  int i,k,maxI;
737  bool mask[hist_size];
738  bool idx[dim];
739  EVectorXd tx(dim);
740  int dfitidx[hist_size];
741  double dfitsort[hist_size];
742  double prct[2] = {25.0,75.0};
743  bool idx_any;
744 
745  for (size_t i = 0 ; i < hist_size ; i++)
746  {
747  dfitsort[i] = 0.0;
748  dfitidx[i] = 0;
749 
750  if (fithist[i] > 0.0)
751  {mask[i] = true;}
752  else
753  {mask[i] = false;}
754  }
755 
756  for (size_t i = 0 ; i < dim ; i++)
757  {diag[i] = C(i,i);}
758 
759  maxI = 0;
760 
761  meandiag = C.trace()/dim;
762 
763  cmaes_myprctile(f_obj, prct, val);
764  value = (val[1] - val[0]) / dim / meandiag / (sigma*sigma);
765 
766  if (value >= std::numeric_limits<double>::max())
767  {
768  auto & v_cl = create_vcluster();
769  std::cout << "Process " << v_cl.rank() << " warning: Non-finite fitness range" << std::endl;
770  value = maxval(fithist,mask);
771  }
772  else if(value == 0.0)
773  {
774  value = minval(fithist,mask);
775  }
776  else if (validfit == 0.0)
777  {
778  for (size_t i = 0 ; i < hist_size ; i++)
779  {fithist[i] = -1.0;}
780  validfit = 1;
781  }
782 
783  for (size_t i = 0; i < hist_size ; i++)
784  {
785  if(fithist[i] < 0.0)
786  {
787  fithist[i] = value;
788  maxI = i;
789  break;
790  }
791  else if(i == hist_size-1)
792  {
793  for (size_t k = 0 ; k < hist_size-1 ; k++)
794  {fithist[k] = fithist[k+1];}
795  fithist[i] = value;
796  maxI = i;
797  }
798  }
799 
800  cmaes_intobounds(xmean,tx,idx,idx_any);
801 
802  if (iniphase)
803  {
804  if (idx_any)
805  {
806  if(maxI == 0)
807  {value = fithist[0];}
808  else
809  {
810  openfpm::vector<fun_index> fitsort(maxI+1);
811  for (size_t i = 0 ; i <= maxI; i++)
812  {
813  fitsort.get(i).f = fithist[i];
814  fitsort.get(i).id = i;
815  }
816 
817  fitsort.sort();
818  for (size_t k = 0; k <= maxI ; k++)
819  {fitsort.get(k).f = fithist[fitsort.get(k).id];}
820 
821  if ((maxI+1) % 2 == 0)
822  {value = (fitsort.get(maxI/2).f+fitsort.get(maxI/2+1).f)/2.0;}
823  else
824  {value = fitsort.get(maxI/2).f;}
825  }
826  for (size_t i = 0 ; i < dim ; i++)
827  {
828  diag[i] = diag[i]/meandiag;
829  weight[i] = 2.0002 * value / diag[i];
830  }
831  if (validfitval == 1.0 && step-last_restart > 2)
832  {
833  iniphase = false;
834  }
835  }
836  }
837 
838  if(idx_any)
839  {
840  tx = xmean - tx;
841  for(size_t i = 0 ; i < dim ; i++)
842  {
843  idx[i] = (idx[i] && (fabs(tx(i)) > 3.0*std::max(1.0,sqrt(dim)/mu_eff) * sigma * sqrt(diag[i])));
844  idx[i] = (idx[i] && (std::copysign(1.0,tx(i)) == std::copysign(1.0,(xmean(i)-xold(i)))) );
845  }
846  for (size_t i = 0 ; i < dim ; i++)
847  {
848  if (idx[i] == true)
849  {
850  weight[i] = pow(1.2,(std::max(1.0,mu_eff/10.0/dim)))*weight[i];
851  }
852  }
853  }
854  double arpenalty[lambda];
855  for (size_t i = 0 ; i < lambda ; i++)
856  {
857  arpenalty[i] = 0.0;
858  for (size_t j = 0 ; j < dim ; j++)
859  {
860  arpenalty[i] += weight[j] * (arxvalid[i](j) - arx[i](j))*(arxvalid[i](j) - arx[i](j));
861  }
862  f_obj.get(i).f += arpenalty[i];
863  }
864 // fitness%sel = fitness%raw + bnd%arpenalty;
865 }
866 
868 
869 double adjust_sigma(double sigma, EMatrixXd & C)
870 {
871  for (size_t i = 0 ; i < dim ; i++)
872  {
873  if (sigma*sqrt(C(i,i)) > 5.0)
874  {sigma = 5.0/sqrt(C(i,i));}
875  }
876 
877  return sigma;
878 }
879 
897 
899 void cma_step(particle_type & vd, int step, double & best,
900  int & best_i, openfpm::vector<double> & best_sol,
901  size_t & fun_eval)
902 {
903  size_t fe = 0;
904  EVectorXd xmean(dim);
905  EVectorXd mean_z(dim);
906  EVectorXd arxvalid[lambda];
907  EVectorXd arx[lambda];
908 
909  for (size_t i = 0 ; i < lambda ; i++)
910  {
911  arx[i].resize(dim);
912  arxvalid[i].resize(dim);
913  }
914 
915  double best_sample = std::numeric_limits<double>::max();
916  openfpm::vector<double> best_sample_sol(dim);
917 
918  openfpm::vector<fun_index> f_obj(lambda);
919 
920  int counteval = step*lambda;
921 
922  auto it = vd.getDomainIterator();
923  while (it.isNext())
924  {
925  auto p = it.get();
926 
927  if (vd.getProp<stop>(p) == true)
928  {++it;continue;}
929 
930  EVectorXd (& arz)[lambda] = vd.getProp<Zeta>(p);
931 
932  // fill the mean vector;
933 
934  fill_vector(vd.getPos(p),xmean);
935 
936  for (size_t j = 0 ; j < lambda ; j++)
937  {
938  vd.getProp<Zeta>(p)[j] = generateGaussianVector<dim>();
939  arx[j] = xmean + vd.getProp<sigma>(p)*vd.getProp<B>(p)*vd.getProp<D>(p)*vd.getProp<Zeta>(p)[j];
940 
941  // sample point has to be inside -5.0 and 5.0
942  for (size_t i = 0 ; i < dim ; i++)
943  {
944  if (arx[j](i) < -5.0)
945  {arxvalid[j](i) = -5.0;}
946  else if (arx[j](i) > 5.0)
947  {arxvalid[j](i) = 5.0;}
948  else
949  {arxvalid[j](i) = arx[j](i);}
950  }
951 
952  f_obj.get(j).f = hybrid_composition<dim>(arxvalid[j]);
953  f_obj.get(j).id = j;
954  fe++;
955 
956  // Get the best ever
957  if (f_obj.get(j).f < best_sample)
958  {
959  best_sample = f_obj.get(j).f;
960 
961  // Copy the new mean as position of the particle
962  for (size_t i = 0 ; i < dim ; i++)
963  {best_sample_sol.get(i) = arxvalid[j](i);}
964  }
965  }
966 
967  // Add penalities for out of bound points
968  cmaes_handlebounds(f_obj,vd.getProp<sigma>(p),
969  vd.getProp<validfit>(p),arxvalid,
970  arx,vd.getProp<Cov_m>(p),
971  xmean,vd.getProp<xold>(p),vd.getProp<weight>(p),
972  vd.getProp<fithist>(p),vd.getProp<iniphase>(p),
973  vd.getProp<validfit>(p),mu_eff,
974  step,vd.getProp<last_restart>(p));
975 
976  f_obj.sort();
977 
978  for (size_t j = 0 ; j < lambda ; j++)
979  {vd.getProp<ord>(p)[j] = f_obj.get(j).id;}
980 
981  vd.getProp<xold>(p) = xmean;
982 
983  // Calculate weighted mean
984 
985  xmean.setZero();
986  mean_z.setZero();
987  for (size_t j = 0 ; j < mu ; j++)
988  {
989  xmean += weight_sample(j)*arx[vd.getProp<ord>(p)[j]];
990  mean_z += weight_sample(j)*vd.getProp<Zeta>(p)[vd.getProp<ord>(p)[j]];
991  }
992 
993  vd.getProp<xmean_st>(p) = xmean;
994  vd.getProp<meanz_st>(p) = mean_z;
995 
996  ++it;
997  }
998 
999  // Find the best point across processors
1000  broadcast_best_solution(vd,best_sol,best,best_sample,best_sample_sol);
1001 
1002  // bool calculate B and D
1003  bool calc_bd = counteval - eigeneval > lambda/(ccov)/dim/10;
1004  if (calc_bd == true)
1005  {eigeneval = counteval;}
1006 
1007  auto it2 = vd.getDomainIterator();
1008  while (it2.isNext())
1009  {
1010  auto p = it2.get();
1011 
1012  if (vd.getProp<stop>(p) == true)
1013  {++it2;continue;}
1014 
1015  xmean = vd.getProp<xmean_st>(p);
1016  mean_z = vd.getProp<meanz_st>(p);
1017 
1018  vd.getProp<path_s>(p) = vd.getProp<path_s>(p)*(1.0 - cs) + sqrt(cs*(2.0-cs)*mu_eff)*vd.getProp<B>(p)*mean_z;
1019 
1020  double hsig = vd.getProp<path_s>(p).norm()/sqrt(1.0-pow((1.0-cs),(2.0*double((step-vd.getProp<last_restart>(p))))))/chiN < 1.4 + 2.0/(dim+1);
1021 
1022  vd.getProp<path_c>(p) = (1-cc)*vd.getProp<path_c>(p) + hsig * sqrt(cc*(2-cc)*mu_eff)*(vd.getProp<B>(p)*vd.getProp<D>(p)*mean_z);
1023 
1024  if (step % N_pso == 0)
1025  {
1026  EMatrixXd C_pso(dim,dim);
1027  updatePso(best_sol,vd.getProp<sigma>(p),xmean,vd.getProp<xold>(p),vd.getProp<B>(p),vd.getProp<D>(p),C_pso);
1028 
1029  // Adapt covariance matrix C
1030  vd.getProp<Cov_m>(p) = (1.0-ccov+(1.0-hsig)*ccov*cc*(2.0-cc)/mu_eff)*vd.getProp<Cov_m>(p) +
1031  ccov*(1.0/mu_eff)*(vd.getProp<path_c>(p)*vd.getProp<path_c>(p).transpose());
1032 
1033  for (size_t i = 0 ; i < mu ; i++)
1034  {vd.getProp<Cov_m>(p) += ccov*(1.0-1.0/mu_eff)*(vd.getProp<B>(p)*vd.getProp<D>(p)*vd.getProp<Zeta>(p)[vd.getProp<ord>(p)[i]])*weight_sample(i)*
1035  (vd.getProp<B>(p)*vd.getProp<D>(p)*vd.getProp<Zeta>(p)[vd.getProp<ord>(p)[i]]).transpose();
1036  }
1037 
1038  vd.getProp<Cov_m>(p) = psoWeight*vd.getProp<Cov_m>(p) + (1.0 - psoWeight)*C_pso;
1039  }
1040  else
1041  {
1042  // Adapt covariance matrix C
1043  vd.getProp<Cov_m>(p) = (1.0-ccov+(1.0-hsig)*ccov*cc*(2.0-cc)/mu_eff)*vd.getProp<Cov_m>(p) +
1044  ccov*(1.0/mu_eff)*(vd.getProp<path_c>(p)*vd.getProp<path_c>(p).transpose());
1045 
1046  for (size_t i = 0 ; i < mu ; i++)
1047  {vd.getProp<Cov_m>(p) += ccov*(1.0-1.0/mu_eff)*(vd.getProp<B>(p)*vd.getProp<D>(p)*vd.getProp<Zeta>(p)[vd.getProp<ord>(p)[i]])*weight_sample(i)*
1048  (vd.getProp<B>(p)*vd.getProp<D>(p)*vd.getProp<Zeta>(p)[vd.getProp<ord>(p)[i]]).transpose();
1049  }
1050  }
1051 
1052  // Numeric error
1053 
1054  double smaller = std::numeric_limits<double>::max();
1055  for (size_t i = 0 ; i < dim ; i++)
1056  {
1057  if (vd.getProp<sigma>(p)*sqrt(vd.getProp<D>(p).diagonal()[i]) > 5.0)
1058  {
1059  if (smaller > 5.0/sqrt(vd.getProp<D>(p).diagonal()[i]))
1060  {smaller = 5.0/sqrt(vd.getProp<D>(p).diagonal()[i]);}
1061  }
1062  }
1063  if (smaller != std::numeric_limits<double>::max())
1064  {vd.getProp<sigma>(p) = smaller;}
1065 
1066  //Adapt step-size sigma
1067  vd.getProp<sigma>(p) = vd.getProp<sigma>(p)*exp((cs/d_amps)*(vd.getProp<path_s>(p).norm()/chiN - 1));
1068 
1069  // Update B and D from C
1070 
1071  if (calc_bd)
1072  {
1073  EMatrixXd trUp = vd.getProp<Cov_m>(p).triangularView<Eigen::Upper>();
1074  EMatrixXd trDw = vd.getProp<Cov_m>(p).triangularView<Eigen::StrictlyUpper>();
1075  vd.getProp<Cov_m>(p) = trUp + trDw.transpose();
1076 
1077  // Eigen decomposition
1078  Eigen::SelfAdjointEigenSolver<EMatrixXd> eig_solver;
1079 
1080  eig_solver.compute(vd.getProp<Cov_m>(p));
1081 
1082  for (size_t i = 0 ; i < eig_solver.eigenvalues().size() ; i++)
1083  {vd.getProp<D>(p).diagonal()[i] = sqrt(eig_solver.eigenvalues()[i]);}
1084  vd.getProp<B>(p) = eig_solver.eigenvectors();
1085 
1086  // Make first component always positive
1087  for (size_t i = 0 ; i < dim ; i++)
1088  {
1089  if (vd.getProp<B>(p)(0,i) < 0)
1090  {vd.getProp<B>(p).col(i) = - vd.getProp<B>(p).col(i);}
1091  }
1092 
1093  EMatrixXd tmp = vd.getProp<B>(p).transpose();
1094  }
1095 
1096  // Copy the new mean as position of the particle
1097  for (size_t i = 0 ; i < dim ; i++)
1098  {vd.getPos(p)[i] = xmean(i);}
1099 
1100  vd.getProp<sigma>(p) = adjust_sigma(vd.getProp<sigma>(p),vd.getProp<Cov_m>(p));
1101 
1102  // Stop conditions
1103  bool stop_tol = true;
1104  bool stop_tolX = true;
1105  for (size_t i = 0 ; i < dim ; i++)
1106  {
1107  stop_tol &= (vd.getProp<sigma>(p)*std::max(fabs(vd.getProp<path_c>(p)(i)),sqrt(vd.getProp<Cov_m>(p)(i,i)))) < stopTolX;
1108  stop_tolX &= vd.getProp<sigma>(p)*sqrt(vd.getProp<D>(p).diagonal()[i]) > stopTolUpX;
1109  }
1110 
1111  vd.getProp<stop>(p) = stop_tol | stop_tolX;
1112 
1113  // Escape flat fitness, or better terminate?
1114  if (f_obj.get(0).f == f_obj.get(std::ceil(0.7*lambda)).f )
1115  {
1116  vd.getProp<sigma>(p) = vd.getProp<sigma>(p)*exp(0.2+cs/d_amps);
1117  std::cout << "warning: flat fitness, consider reformulating the objective";
1118 
1119  // Stop it
1120  vd.getProp<stop>(p) = true;
1121  }
1122 
1123  if (vd.getProp<stop>(p) == true)
1124  {std::cout << "Stopped" << std::endl;}
1125 
1126  if (restart_cma && vd.getProp<stop>(p) == true)
1127  {
1128  std::cout << "------- Restart #" << std::endl;
1129 
1130  std::cout << "---------------------------------" << std::endl;
1131  std::cout << "Best: " << best << " " << fun_eval << std::endl;
1132  std::cout << "---------------------------------" << std::endl;
1133 
1134  vd.getProp<last_restart>(p) = step;
1135  vd.getProp<xold>(p).setZero();
1136 
1137  for (size_t i = 0 ; i < vd.getProp<D>(p).diagonal().size() ; i++)
1138  {vd.getProp<D>(p).diagonal()[i] = 1.0;}
1139  vd.getProp<B>(p).resize(dim,dim);
1140  vd.getProp<B>(p).setIdentity();
1141  vd.getProp<Cov_m>(p) = vd.getProp<B>(p)*vd.getProp<D>(p)*vd.getProp<D>(p)*vd.getProp<B>(p);
1142  vd.getProp<path_s>(p).resize(dim);
1143  vd.getProp<path_s>(p).setZero(dim);
1144  vd.getProp<path_c>(p).resize(dim);
1145  vd.getProp<path_c>(p).setZero(dim);
1146  vd.getProp<stop>(p) = false;
1147  vd.getProp<iniphase>(p) = true;
1148  vd.getProp<last_restart>(p) = 0;
1149  vd.getProp<sigma>(p) = 2.0;
1150 
1151  // a different point in space
1152  for (size_t i = 0 ; i < dim ; i++)
1153  {
1154  // we define x, assign a random position between 0.0 and 1.0
1155  vd.getPos(p)[i] = 10.0*(double)rand() / RAND_MAX - 5.0;
1156  }
1157 
1158  // Initialize the bound history
1159 
1160  for (size_t i = 0 ; i < hist_size ; i++)
1161  {vd.getProp<fithist>(p)[i] = -1.0;}
1162  vd.getProp<fithist>(p)[0] = 1.0;
1163  vd.getProp<validfit>(p) = 0.0;
1164  }
1165 
1166  ++it2;
1167  }
1168 
1169  auto & v_cl = create_vcluster();
1170  v_cl.sum(fe);
1171  v_cl.execute();
1172 
1173  fun_eval += fe;
1174 }
1175 
1177 
1191 int main(int argc, char* argv[])
1192 {
1193  // initialize the library
1194  openfpm_init(&argc,&argv);
1195 
1196  auto & v_cl = create_vcluster();
1197 
1198  // Here we define our domain a 2D box with internals from 0 to 1.0 for x and y
1199  Box<dim,double> domain;
1200 
1201  for (size_t i = 0 ; i < dim ; i++)
1202  {
1203  domain.setLow(i,0.0);
1204  domain.setHigh(i,1.0);
1205  }
1206 
1207  // Here we define the boundary conditions of our problem
1208  size_t bc[dim];
1209  for (size_t i = 0 ; i < dim ; i++)
1210  {bc[i] = NON_PERIODIC;};
1211 
1212  prepare_f15<dim>();
1213 
1214  // extended boundary around the domain, and the processor domain
1215  Ghost<dim,double> g(0.0);
1216 
1217  particle_type vd(16,domain,bc,g);
1218 
1219  // Initialize constants
1220 
1221  stop_fitness = 1e-10;
1222  size_t stopeval = 1e3*dim*dim;
1223 
1224  // Strategy parameter setting: Selection
1225  init_weight();
1226 
1227  // Strategy parameter setting: Adaptation
1228  cc = 4.0 / (dim+4.0);
1229  cs = (mu_eff+2.0) / (double(dim)+mu_eff+3.0);
1230  ccov = (1.0/mu_eff) * 2.0/((dim+1.41)*(dim+1.41)) +
1231  (1.0 - 1.0/mu_eff)* std::min(1.0,(2.0*mu_eff-1.0)/((dim+2.0)*(dim+2.0) + mu_eff));
1232  d_amps = 1 + 2*std::max(0.0, sqrt((mu_eff-1.0)/(dim+1))-1) + cs;
1233 
1234  chiN = sqrt(dim)*(1.0-1.0/(4.0*dim)+1.0/(21.0*dim*dim));
1235 
1237 
1238 
1239  // initialize the srand
1240  int seed = 24756*v_cl.rank()*v_cl.rank() + time(NULL);
1241  srand(seed);
1242 
1243  auto it = vd.getDomainIterator();
1244 
1245  while (it.isNext())
1246  {
1247  auto p = it.get();
1248 
1249  for (size_t i = 0 ; i < dim ; i++)
1250  {
1251  // we define x, assign a random position between 0.0 and 1.0
1252  vd.getPos(p)[i] = 10.0*(double)rand() / RAND_MAX - 5.0;
1253  }
1254 
1255  vd.getProp<sigma>(p) = 2.0;
1256 
1257  // Initialize the covariant Matrix,B and D to identity
1258 
1259  vd.getProp<D>(p).resize(dim);
1260  for (size_t i = 0 ; i < vd.getProp<D>(p).diagonal().size() ; i++)
1261  {vd.getProp<D>(p).diagonal()[i] = 1.0;}
1262  vd.getProp<B>(p).resize(dim,dim);
1263  vd.getProp<B>(p).setIdentity();
1264  vd.getProp<Cov_m>(p) = vd.getProp<B>(p)*vd.getProp<D>(p)*vd.getProp<D>(p)*vd.getProp<B>(p);
1265  vd.getProp<path_s>(p).resize(dim);
1266  vd.getProp<path_s>(p).setZero(dim);
1267  vd.getProp<path_c>(p).resize(dim);
1268  vd.getProp<path_c>(p).setZero(dim);
1269  vd.getProp<stop>(p) = false;
1270  vd.getProp<iniphase>(p) = true;
1271  vd.getProp<last_restart>(p) = 0;
1272 
1273  // Initialize the bound history
1274 
1275  for (size_t i = 0 ; i < hist_size ; i++)
1276  {vd.getProp<fithist>(p)[i] = -1.0;}
1277  vd.getProp<fithist>(p)[0] = 1.0;
1278  vd.getProp<validfit>(p) = 0.0;
1279 
1280  // next particle
1281  ++it;
1282  }
1283 
1284  if (v_cl.rank() == 0)
1285  {std::cout << "Starting PS-CMA-ES" << std::endl;}
1286 
1287  double best = 0.0;
1288  int best_i = 0;
1289 
1290  best = std::numeric_limits<double>::max();
1291  openfpm::vector<double> best_sol(dim);
1292  // now do several iteration
1293 
1294  int stop_cond = 0;
1295  size_t fun_eval = 0;
1296  int i = 0;
1297  while (fun_eval < max_fun_eval && best > 120.000001)
1298  {
1299  // sample offspring
1300  cma_step(vd,i+1,best,best_i,best_sol,fun_eval);
1301 
1302  i++;
1303  }
1304 
1305  if (v_cl.rank() == 0)
1306  {
1307  std::cout << "Best solution: " << best << " with " << fun_eval << std::endl;
1308  std::cout << "at: " << std::endl;
1309 
1310  for (size_t i = 0 ; i < best_sol.size() ; i++)
1311  {
1312  std::cout << best_sol.get(i) << " ";
1313  }
1314  }
1315 
1316  openfpm_finalize();
1317 
1319 
1329 }
1330 
1331 #endif
Derivative second order on h (spacing)
Definition: Derivative.hpp:28
size_t size()
Stub size.
Definition: map_vector.hpp:211
Definition: Ghost.hpp:39
__device__ __host__ void setHigh(int i, T val)
set the high interval of the box
Definition: Box.hpp:544
__device__ __host__ void setLow(int i, T val)
set the low interval of the box
Definition: Box.hpp:533
KeyT const ValueT ValueT OffsetIteratorT OffsetIteratorT int
[in] The number of segments that comprise the sorting data
This class represent an N-dimensional box.
Definition: Box.hpp:60
Distributed vector.
aggregate of properties, from a list of object if create a struct that follow the OPENFPM native stru...
Definition: aggregate.hpp:214
It model an expression expr1 + ... exprn.
Definition: sum.hpp:92
Implementation of 1-D std::vector like structure.
Definition: map_vector.hpp:202