/** \file aga.hpp \brief asexual genetic algorithm method */ #ifndef AGA_METHOD #define AGA_METHOD #define OPT_HEADER #include <core/optimizer.hpp> //#include <blitz/array.h> #include <limits> #include <cstdlib> #include <core/opt_traits.hpp> #include <cassert> #include <cmath> #include <vector> #include <algorithm> /* * */ #include <iostream> using std::cout; using std::endl; namespace opt_utilities { template <typename rT,typename pT> struct vp_pair { rT v; pT p; }; template <typename rT,typename pT> class vp_comp { public: bool operator()(const vp_pair<rT,pT>& x1, const vp_pair<rT,pT>& x2) { return x1.v<x2.v; } }; /** \brief Implement of the asexual genetic algorithm 2009A&A...501.1259C http://adsabs.harvard.edu/abs/2009arXiv0905.3712C \tparam rT return type of the object function \tparam pT parameter type of the object function */ template <typename rT,typename pT> class aga_method :public opt_method<rT,pT> { public: typedef pT array1d_type; private: int n1,n2,n0; func_obj<rT,pT>* p_fo; optimizer<rT,pT>* p_optimizer; rT threshold; pT lower_bound; pT upper_bound; typename element_type_trait<pT>::element_type decay_factor; pT reproduction_box; std::vector<vp_pair<rT,pT> > samples; std::vector<pT> buffer; private: typename element_type_trait<pT>::element_type uni_rand (typename element_type_trait<pT>::element_type x1, typename element_type_trait<pT>::element_type x2) { return rand()/(double)RAND_MAX*(x2-x1)+x1; } private: rT func(const pT& x) { assert(p_fo!=0); return p_fo->eval(x); } public: aga_method(int _n1,int _n2) :n1(_n1),n2(_n2),n0(n1*n2+n1), p_fo(0),p_optimizer(0),threshold(1e-4), decay_factor(.999), samples(n1*n2+n1) { } aga_method() :n1(50),n2(20),n0(n1*n2+n1), p_fo(0),p_optimizer(0),threshold(1e-4), decay_factor(.999), samples(n1*n2+n1) { } virtual ~aga_method() { }; aga_method(const aga_method<rT,pT>& rhs) :n1(rhs.n1),n2(rhs.n2),n0(rhs.n0), p_fo(rhs.p_fo),p_optimizer(rhs.p_optimizer), threshold(rhs.threshold), decay_factor(rhs.decay_factor), samples(rhs.samples) { } aga_method<rT,pT>& operator=(const aga_method<rT,pT>& rhs) { threshold=rhs.threshold; p_fo=rhs.p_fo; p_optimizer=rhs.p_optimizer; samples=rhs.samples; n1=rhs.n1; n2=rhs.n2; n0=rhs.n0; } void set_decay_factor(typename element_type_trait<pT>::element_type _decay_factor) { decay_factor=_decay_factor; } opt_method<rT,pT>* do_clone()const { return new aga_method<rT,pT>(*this); } void do_set_start_point(const array1d_type& p) { for(size_t i=0;i<samples.size();++i) { // cout<<i<<" "; resize(samples[i].p,get_size(p)); // std::cout<<samples[i].p.size()<<std::endl;; for(size_t j=0;j<get_size(p);++j) { set_element(samples[i].p,j, uni_rand(get_element(lower_bound,j), get_element(upper_bound,j)) ); } } } array1d_type do_get_start_point()const { return array1d_type(); } void do_set_lower_limit(const array1d_type& p) { opt_eq(lower_bound,p); } array1d_type do_get_lower_limit()const { return lower_bound; } void do_set_upper_limit(const array1d_type& p) { opt_eq(upper_bound,p); } array1d_type do_get_upper_limit()const { return upper_bound; } void do_set_precision(rT t) { threshold=t; } rT do_get_precision()const { return threshold; } void do_set_optimizer(optimizer<rT,pT>& o) { p_optimizer=&o; p_fo=p_optimizer->ptr_func_obj(); } bool iter() { rT sum2=0; rT sum=0; for(size_t i=0;i<samples.size();++i) { samples[i].v=func(samples[i].p); sum2+=samples[i].v*samples[i].v; sum+=samples[i].v; } std::sort(samples.begin(),samples.end(),vp_comp<rT,pT>()); if(sum2/samples.size()-pow(sum/samples.size(),2)<threshold) { return false; } pT lb(get_size(samples[0].p)); pT ub(get_size(samples[0].p)); for(int i=0;i<n2;++i) { pT p(samples[i].p); for(size_t j=0;j<get_size(p);++j) { if(i==0) { ub[j]=p[j]; lb[j]=p[j]; } ub[j]=std::max(ub[j],p[j]); lb[j]=std::min(lb[j],p[j]); set_element(p,j, get_element(p,j)+ uni_rand(-get_element(reproduction_box,j), get_element(reproduction_box,j))); if(get_element(p,j)>get_element(upper_bound,j)) { set_element(p,j,get_element(upper_bound,j)); } if(get_element(p,j)<get_element(lower_bound,j)) { set_element(p,j,get_element(lower_bound,j)); } } buffer[i]=p; } for(int i=0;i<n1;++i) { for(int j=0;j<n2;++j) { pT p(samples[i].p); for(size_t k=0;k<get_size(p);++k) { set_element(samples[i*n2+j+n1].p,k, (get_element(samples[i].p,k)+ get_element(buffer[j],k))/2.); ub[k]=std::max(ub[k],samples[i*n2+j+n1].p[k]); lb[k]=std::min(lb[k],samples[i*n2+j+n1].p[k]); } } } double n_per_dim=pow((double)n0,1./get_size(lower_bound)); for(size_t i=0;i<get_size(reproduction_box);++i) { // set_element(reproduction_box,i, //get_element(reproduction_box,i)*decay_factor); set_element(reproduction_box,i, (get_element(ub,i)- get_element(ub,i))/n_per_dim); } return true; } pT do_optimize() { srand(time(0)); buffer.resize(n2); double n_per_dim=pow((double)n0,1./get_size(lower_bound)); resize(reproduction_box,get_size(lower_bound)); for(size_t i=0;i<get_size(lower_bound);++i) { set_element(reproduction_box,i, (get_element(upper_bound,i)- get_element(lower_bound,i))/n_per_dim); } while(iter()){} return samples.begin()->p; } }; } #endif //EOF