55 double chi( std::size_t n ) {
56 return( std::sqrt(
static_cast<double>( n ) )*(1. - 1./(4.*n) + 1./(21.*n*n)) );
67 {
return "VDCMA-ES"; }
71 return unsigned( 4. + ::floor( 3. * ::log(
static_cast<double>( dimension ) ) ) );
86 double sigma = m_initialSigma;
87 if(m_initialSigma == 0)
88 sigma = 1.0/std::sqrt(
double(p.size()));
107 m_numberOfVariables = function.numberOfVariables();
110 m_sigma = initialSigma;
112 m_mean = blas::repeat(0.0,m_numberOfVariables);
113 m_vn.resize(m_numberOfVariables);
114 for(std::size_t i = 0; i != m_numberOfVariables;++i){
115 m_vn(i) =
random::uni(*mpe_rng,0,1.0/m_numberOfVariables);
117 m_normv = norm_2(m_vn);
120 m_D = blas::repeat(1.0,m_numberOfVariables);
121 m_evolutionPathC = blas::repeat(0.0,m_numberOfVariables);
122 m_evolutionPathSigma = blas::repeat(0.0,m_numberOfVariables);
125 m_mean = initialSearchPoint;
126 m_best.point = initialSearchPoint;
127 m_best.value = function(initialSearchPoint);
132 m_weights.resize(m_mu);
133 for (std::size_t i = 0; i < m_mu; i++){
134 m_weights(i) = ::log(
mu + 0.5) - ::log(1. + i);
136 m_weights /= sum(m_weights);
139 m_muEff = 1. / sum(
sqr(m_weights));
140 m_cSigma = 0.5/(1+std::sqrt(m_numberOfVariables/m_muEff));
141 m_dSigma = 1. + 2. * std::max(0., std::sqrt((m_muEff-1.)/(m_numberOfVariables+1)) - 1.) + m_cSigma;
143 m_cC = (4. + m_muEff / m_numberOfVariables) / (m_numberOfVariables + 4. + 2 * m_muEff / m_numberOfVariables);
144 double correction = (m_numberOfVariables - 5.0)/6.0;
145 m_c1 = correction*2 / (
sqr(m_numberOfVariables + 1.3) + m_muEff);
146 m_cMu = std::min(1. - m_c1, correction* 2 * (m_muEff - 2. + 1./m_muEff) / (
sqr(m_numberOfVariables + 2) + m_muEff));
152 std::vector< IndividualType > offspring( m_lambda );
155 for( std::size_t i = 0; i < offspring.size(); i++ ) {
156 createSample(offspring[i].
searchPoint(),offspring[i].chromosome());
158 penalizingEvaluator( function, offspring.begin(), offspring.end() );
161 std::vector< IndividualType > parents( m_mu );
163 selection(offspring.begin(),offspring.end(),parents.begin(), parents.end());
166 updateStrategyParameters( parents );
168 m_best.point= parents[ 0 ].searchPoint();
169 m_best.value= parents[ 0 ].unpenalizedFitness();
190 m_initialSigma = initialSigma;
195 RealVector
const&
mean()
const {
206 return m_evolutionPathC;
211 return m_evolutionPathSigma;
215 std::size_t
mu()
const {
239 RealVector m( m_numberOfVariables, 0. );
240 RealVector z( m_numberOfVariables, 0. );
242 for( std::size_t j = 0; j < offspring.size(); j++ ){
243 noalias(m) += m_weights( j ) * offspring[j].searchPoint();
244 noalias(z) += m_weights( j ) * offspring[j].chromosome();
248 double b=(1/std::sqrt(1+
sqr(m_normv))-1);
249 noalias(z)+= b*inner_prod(z,m_vn)*m_vn;
252 noalias(m_evolutionPathSigma) = (1. - m_cSigma)*m_evolutionPathSigma + std::sqrt( m_cSigma * (2. - m_cSigma) * m_muEff ) * z;
254 double hSigLHS = norm_2( m_evolutionPathSigma ) / std::sqrt(1. - pow((1 - m_cSigma), 2.*(m_counter+1)));
255 double hSigRHS = (1.4 + 2 / (m_numberOfVariables+1.)) * chi( m_numberOfVariables );
257 if(hSigLHS < hSigRHS) hSig = 1.;
258 noalias(m_evolutionPathC) = (1. - m_cC ) * m_evolutionPathC + hSig * std::sqrt( m_cC * (2. - m_cC) * m_muEff ) * (m - m_mean) / m_sigma;
267 RealVector meanS(m_numberOfVariables,0.0);
268 RealVector meanT(m_numberOfVariables,0.0);
269 for(std::size_t j = 0; j !=
mu(); ++j){
270 computeSAndTFirst(offspring[j].chromosome(),meanS,meanT,m_cMu*m_weights(j));
272 computeSAndTFirst(m_evolutionPathC/m_D,meanS,meanT,hSig*m_c1);
275 computeSAndTSecond(meanS,meanT);
278 noalias(m_D) += m_D*meanS;
279 noalias(m_vn) = m_vn*m_normv+meanT/m_normv;
281 m_normv = norm_2(m_vn);
285 m_sigma *= std::exp( (m_cSigma / m_dSigma) * (norm_2(m_evolutionPathSigma)/ chi( m_numberOfVariables ) - 1.) );
293 void createSample(RealVector& x,RealVector& y)
const{
294 x.resize(m_numberOfVariables);
295 y.resize(m_numberOfVariables);
296 for(std::size_t i = 0; i != m_numberOfVariables; ++i){
299 double a = std::sqrt(1+
sqr(m_normv))-1;
300 a *= inner_prod(y,m_vn);
302 noalias(x) = m_mean+ m_sigma*m_D*y;
308 void computeSAndTFirst(RealVector
const& y, RealVector& s,RealVector& t,
double weight )
const{
309 if(weight == 0)
return;
310 double yvn = inner_prod(y,m_vn);
311 double normv2 =
sqr(m_normv);
312 double gammav = 1+normv2;
314 noalias(s) += weight*(
sqr(y) - (normv2/gammav*yvn)*(y*m_vn)- 1.0);
316 noalias(t) += weight*(yvn*y - 0.5*(
sqr(yvn)+gammav)*m_vn);
320 void computeSAndTSecond(RealVector& s,RealVector& t)
const{
321 RealVector vn2 = m_vn*m_vn;
322 double normv2 =
sqr(m_normv);
323 double gammav = 1+normv2;
325 double alpha =
sqr(normv2)+(2*gammav - std::sqrt(gammav))/max(vn2);
326 alpha=std::sqrt(alpha);
328 alpha = std::min(alpha,1.0);
330 double b=-(1-
sqr(alpha))*
sqr(normv2)/gammav+2*
sqr(alpha);
331 RealVector A= 2.0 - (b+2*
sqr(alpha))*vn2;
332 RealVector invAvn2= vn2/A;
335 noalias(s) -= alpha/gammav*((2+normv2)*(m_vn*t)-normv2*inner_prod(m_vn,t)*vn2);
337 noalias(s) = s/A -b*inner_prod(s,invAvn2)/(1+b*inner_prod(vn2,invAvn2))*invAvn2;
339 noalias(t) -= alpha*((2+normv2)*(m_vn*s)-inner_prod(s,vn2)*m_vn);
342 std::size_t m_numberOfVariables;
344 std::size_t m_lambda;
346 double m_initialSigma;
356 RealVector m_weights;
358 RealVector m_evolutionPathC;
359 RealVector m_evolutionPathSigma;
370 random::rng_type* mpe_rng;