25 #include <boost/random/uniform_int.hpp>
26 #include <boost/random/uniform_real.hpp>
31 #include "pso_generational_racing.h"
32 #include "../problem/base_stochastic.h"
34 namespace pagmo {
namespace algorithm {
36 using namespace util::racing;
58 pso_generational_racing::pso_generational_racing(
int gen,
double omega,
double eta1,
double eta2,
double vcoeff,
int variant,
int neighb_type,
int neighb_param,
unsigned int nr_eval_per_x,
unsigned int max_fevals):
base(), m_gen(gen), m_omega(omega), m_eta1(eta1), m_eta2(eta2), m_vcoeff(vcoeff), m_variant(variant), m_neighb_type(neighb_type), m_neighb_param(neighb_param), m_nr_eval_per_x(nr_eval_per_x), m_fevals(0), m_max_fevals(max_fevals) {
60 pagmo_throw(value_error,
"number of generations must be nonnegative");
63 if (m_omega < 0 || m_omega > 1) {
66 pagmo_throw(value_error,
"the particles' inertia must be in the [0,1] range");
69 pagmo_throw(value_error,
"the particles' constriction coefficient must be in the [0,1] range");
72 if (eta1 < 0 || eta2 < 0 || eta1 > 4 || eta2 > 4) {
73 pagmo_throw(value_error,
"the eta parameters must be in the [0,4] range");
76 if (vcoeff <= 0 || vcoeff > 1) {
77 pagmo_throw(value_error,
"fraction of variables' range in which velocity may vary should be in ]0,1]");
80 if (variant < 1 || variant > 6) {
81 pagmo_throw(value_error,
"algorithm variant must be one of 1 ... 6");
84 if (neighb_type < 1 || neighb_type > 4) {
85 pagmo_throw(value_error,
"swarm topology variant must be one of 1 ... 4");
100 void pso_generational_racing::racing__construct_race_environment(
util::racing::race_pop & race_structure,
const problem::base& prob,
const std::vector<decision_vector> &x_list1,
const std::vector<decision_vector> &x_list2 )
const
102 util::racing::racing_population lbpop( prob );
103 for(
unsigned int p = 0; p < x_list1.size(); p++ ){
104 lbpop.push_back_noeval( x_list1[p] );
106 for(
unsigned int p = 0; p < x_list2.size(); p++ ){
107 lbpop.push_back_noeval( x_list2[p] );
120 std::pair<population::size_type, unsigned int> pso_generational_racing::racing__race_for_winner( util::racing::race_pop &race_structure,
int idx1,
int idx2,
unsigned int max_fevals)
const
123 if(!(idx1<0 && idx2<0) && !(idx1>=0 && idx2>=0)){
124 pagmo_throw(value_error,
"The pair must either be both -1 (race all) or both explicitly specified.");
129 bool use_data_count_termination =
false;
131 std::vector<population::size_type> active_set;
134 active_set.resize(race_structure.size());
138 if(use_data_count_termination){
139 max_fevals /= race_structure.size();
144 active_set.resize(2);
145 active_set[0] = idx1;
146 active_set[1] = idx2;
147 if(use_data_count_termination){
151 std::pair<std::vector<population::size_type>,
unsigned int> res;
152 if(use_data_count_termination){
156 res = race_structure.run(1, 0, max_fevals, 0.001, active_set,
race_pop::MAX_BUDGET,
true,
false);
158 return std::make_pair(res.first[0], res.second);
165 for(
unsigned int i = 0; i < m_nr_eval_per_x; i++){
168 for(
unsigned int j = 0; j < f.size(); j++){
169 f[j] += f_tmp[j] / m_nr_eval_per_x;
175 void pso_generational_racing::particle__average_fitness_set_best(
const problem::base &prob, std::vector<fitness_vector> &F,
population::size_type& best_idx,
fitness_vector& best_fit,
const std::vector<decision_vector> &X)
const
177 F = std::vector<fitness_vector>(X.size(),
fitness_vector(prob.get_f_dimension()));
178 for(
unsigned int i = 0; i < X.size(); i++){
179 particle__average_fitness(prob, F[i], X[i]);
185 if(prob.compare_fitness(F[i], best_fit)){
227 pagmo_throw(value_error,
"There is no continuous part in the problem decision vector for PSO to optimise");
230 if( prob_c_dimension != 0 ){
231 pagmo_throw(value_error,
"The problem is not box constrained and PSO is not suitable to solve it");
234 if( prob_f_dimension != 1 ){
235 pagmo_throw(value_error,
"The problem is not single objective and PSO is not suitable to solve it");
239 if (swarm_size == 0 || m_gen == 0) {
247 catch (
const std::bad_cast& e){
250 std::cout <<
"The problem is not stochastic and racing based PSO is not suitable to solve it" << std::endl;
255 std::vector<double> dummy(Dc,0);
257 std::vector<decision_vector> X(swarm_size,dummy);
258 std::vector<fitness_vector> fit(swarm_size);
260 std::vector<decision_vector > V(swarm_size,dummy);
262 std::vector<decision_vector> lbX(swarm_size,dummy);
263 std::vector<fitness_vector> lbfit(swarm_size);
266 std::vector< std::vector<int> > neighb(swarm_size);
271 bool best_fit_improved;
284 for( d = 0; d < Dc; d++ ){
285 vwidth = ( ub[d] - lb[d] ) * m_vcoeff;
286 minv[d] = -1.0 * vwidth;
291 for( p = 0; p < swarm_size; p++ ){
298 for( p = 0; p < swarm_size; p++ ){
304 switch( m_neighb_type ){
305 case 1: initialize_topology__gbest( pop, best_neighb, best_fit, neighb );
break;
306 case 3: initialize_topology__von( neighb );
break;
307 case 4: initialize_topology__adaptive_random( neighb );
308 best_idx = pop.get_best_idx();
309 best_fit = lbfit[ best_idx ];
312 default: initialize_topology__lbest( neighb );
320 unsigned int racing_seed =
m_urng();
324 racing__construct_race_environment(race_lbX, pop.problem(), lbX, std::vector<decision_vector>());
326 if( m_neighb_type == 1 ){
329 std::pair<population::size_type, unsigned int> res
330 = racing__race_for_winner(race_lbX, -1, -1, pop.size() * m_nr_eval_per_x);
331 best_idx = res.first;
332 m_fevals += res.second;
336 best_neighb = lbX[ best_idx ];
337 best_fit = lbfit[ best_idx ];
341 double acceleration_coefficient = m_eta1 + m_eta2;
347 bool forced_terminate =
false;
351 bool racing_opt__race_neighbourhood =
true;
357 while( g < m_gen && m_fevals < m_max_fevals ){
361 unsigned int cur_racing_seed =
m_urng();
363 race_lbX_and_X.
set_seed(cur_racing_seed);
366 for( p = 0; p < swarm_size; p++ ){
372 if( m_neighb_type != 1 && m_variant != 6){
373 if( !racing_opt__race_neighbourhood ){
374 best_neighb = particle__get_best_neighbor( p, neighb, lbX, lbfit, prob );
377 best_neighb = particle__racing_get_best_neighbor( p, neighb, lbX, race_lbX );
384 if(m_fevals > m_max_fevals){
385 m_fevals = m_max_fevals;
386 forced_terminate =
true;
393 if( m_variant == 1 ){
394 for( d = 0; d < Dc; d++ ){
397 V[p][d] = m_omega * V[p][d] + m_eta1 * r1 * (lbX[p][d] - X[p][d]) + m_eta2 * r2 * (best_neighb[d] - X[p][d]);
404 else if( m_variant == 2 ){
405 for( d = 0; d < Dc; d++ ){
407 V[p][d] = m_omega * V[p][d] + m_eta1 * r1 * (lbX[p][d] - X[p][d]) + m_eta2 * r1 * (best_neighb[d] - X[p][d]);
413 else if( m_variant == 3 ){
416 for( d = 0; d < Dc; d++ ){
417 V[p][d] = m_omega * V[p][d] + m_eta1 * r1 * (lbX[p][d] - X[p][d]) + m_eta2 * r2 * (best_neighb[d] - X[p][d]);
424 else if( m_variant == 4 ){
426 for( d = 0; d < Dc; d++ ){
427 V[p][d] = m_omega * V[p][d] + m_eta1 * r1 * (lbX[p][d] - X[p][d]) + m_eta2 * r1 * (best_neighb[d] - X[p][d]);
444 else if( m_variant == 5 ){
445 for( d = 0; d < Dc; d++ ){
448 V[p][d] = m_omega * ( V[p][d] + m_eta1 * r1 * (lbX[p][d] - X[p][d]) + m_eta2 * r2 * (best_neighb[d] - X[p][d]) );
462 else if( m_variant == 6 ){
463 for( d = 0; d < Dc; d++ ){
465 for( n = 0; n < neighb[p].size(); n++ )
466 sum_forces +=
m_drng() * acceleration_coefficient * ( lbX[ neighb[p][n] ][d] - X[p][d] );
468 V[p][d] = m_omega * ( V[p][d] + sum_forces / neighb[p].size() );
473 if(forced_terminate){
478 for( p = 0; p < swarm_size; p++ ){
481 for( d = 0; d < Dc; d++ ){
483 if( V[p][d] > maxv[d] )
486 else if( V[p][d] < minv[d] )
490 new_x = X[p][d] + V[p][d];
502 else if( new_x > ub[d] ){
512 std::vector<bool> local_bests_improved = std::vector<bool>(lbX.size(),
false);
519 racing__construct_race_environment(race_lbX_and_X, pop.problem(), lbX, X);
522 for( p = 0; p < swarm_size && !forced_terminate; p++ ){
523 std::pair<population::size_type, unsigned int> res =
524 racing__race_for_winner(race_lbX_and_X, p, p + swarm_size, 2 * m_nr_eval_per_x);
525 m_fevals += res.second;
526 if (m_fevals > m_max_fevals){
527 forced_terminate =
true;
530 if(res.first == p+swarm_size){
531 local_bests_improved[p] =
true;
537 if(forced_terminate){
544 std::vector<fitness_vector> averaged_fitness =
546 for(
unsigned int i = 0; i < swarm_size; i++){
547 lbfit[i] = averaged_fitness[i];
548 fit[i] = averaged_fitness[i+swarm_size];
552 best_fit_improved =
false;
555 for( p = 0; p < swarm_size; p++ ){
557 if(local_bests_improved[p]){
566 best_fit_improved =
true;
568 pop.push_back(lbX[p]);
581 racing__construct_race_environment(race_lbX, pop.problem(), lbX, std::vector<decision_vector>());
586 if( m_neighb_type == 1 ){
588 std::pair<population::size_type, unsigned int> res =
589 racing__race_for_winner(race_lbX, -1, -1, swarm_size * m_nr_eval_per_x);
594 m_fevals += res.second;
599 best_fit_improved =
true;
601 best_neighb = lbX[ best_idx ];
602 best_fit = lbfit[ best_idx ];
604 if( m_neighb_type == 4 ){
608 best_neighb = lbX[ best_idx ];
609 best_fit = lbfit[ best_idx ];
610 for( p = 0; p < swarm_size; p++ ){
613 best_neighb = lbX[p];
615 best_fit_improved =
true;
622 if( m_neighb_type == 4 && !best_fit_improved )
624 initialize_topology__adaptive_random( neighb );
628 std::cout <<
"PSO terminated: gen = " << g <<
", incurred fevals = " << m_fevals << std::endl;
642 decision_vector pso_generational_racing::particle__get_best_neighbor(
population::size_type pidx, std::vector< std::vector<int> > &neighb,
const std::vector<decision_vector> &lbX,
const std::vector<fitness_vector> &lbfit,
const problem::base &prob)
const
646 switch( m_neighb_type ){
649 pagmo_throw(value_error,
"particle__get_best_neighbor() invoked while using a gbest swarm topology");
656 bnidx = neighb[pidx][0];
657 for( nidx = 1; nidx < neighb[pidx].size(); nidx++ )
658 if( prob.
compare_fitness( lbfit[ neighb[pidx][nidx] ], lbfit[ bnidx ] ) )
659 bnidx = neighb[pidx][nidx];
665 decision_vector pso_generational_racing::particle__racing_get_best_neighbor(
population::size_type pidx, std::vector< std::vector<int> > &neighb,
const std::vector<decision_vector> &lbX, util::racing::race_pop& race)
const
667 std::vector<population::size_type> active_indices;
669 bool repeated =
false;
670 for(
unsigned int i = 0; i < active_indices.size(); i++){
673 if((
unsigned int)neighb[pidx][nidx] == active_indices[i]){
679 active_indices.push_back(neighb[pidx][nidx]);
682 std::pair<std::vector<population::size_type>,
unsigned int> race_res = race.run(2, 0, neighb[pidx].size() * m_nr_eval_per_x, 0.01, active_indices,
race_pop::MAX_BUDGET,
true,
false);
684 std::vector<population::size_type> winners = race_res.first;
685 m_fevals += race_res.second;
686 return lbX[winners[0]];
708 void pso_generational_racing::initialize_topology__gbest(
const population &pop,
decision_vector &gbX,
fitness_vector &gbfit, std::vector< std::vector<int> > &neighb )
const
712 gbX = pop.champion().x;
713 gbfit = pop.champion().f;
719 if( m_variant == 6 ){
721 for( i = 0; i < neighb.size(); i++ )
722 neighb[0].push_back( i );
723 for( i = 1; i < neighb.size(); i++ )
724 neighb[i] = neighb[0];
741 void pso_generational_racing::initialize_topology__lbest( std::vector< std::vector<int> > &neighb )
const
743 int swarm_size = neighb.size();
747 int radius = m_neighb_param / 2;
749 for( pidx = 0; pidx < swarm_size; pidx++ ){
750 for( j = -radius; j <= radius; j++ ){
752 nidx = (pidx + j) % swarm_size;
753 if( nidx < 0 ) nidx = swarm_size + nidx;
754 neighb[pidx].push_back( nidx );
788 void pso_generational_racing::initialize_topology__von( std::vector< std::vector<int> > &neighb )
const
790 int swarm_size = neighb.size();
796 rows = std::sqrt( swarm_size );
797 while( swarm_size % rows != 0 )
799 cols = swarm_size / rows;
801 for( pidx = 0; pidx < swarm_size; pidx++ ){
805 for( nidx = 0; nidx < 4; nidx++ ){
806 n_x = ( p_x + vonNeumann_neighb_diff[nidx][0] ) % cols;
if( n_x < 0 ) n_x = cols + n_x;
807 n_y = ( p_y + vonNeumann_neighb_diff[nidx][1] ) % rows;
if( n_y < 0 ) n_y = rows + n_y;
809 neighb[pidx].push_back( n_y * cols + n_x );
837 void pso_generational_racing::initialize_topology__adaptive_random( std::vector< std::vector<int> > &neighb )
const
839 int swarm_size = neighb.size();
844 for( pidx = 0; pidx < swarm_size; pidx++ )
845 neighb[pidx].clear();
848 for( pidx = 0; pidx < swarm_size; pidx++ ){
851 neighb[pidx].push_back( pidx );
853 for( j = 1; j < m_neighb_param; j++ ){
854 nidx =
m_drng() * swarm_size;
855 neighb[nidx].push_back( pidx );
866 return "PSO - Generational with racing";
876 std::ostringstream s;
877 s <<
"gen:" << m_gen <<
' ';
878 s <<
"omega:" << m_omega <<
' ';
879 s <<
"eta1:" << m_eta1 <<
' ';
880 s <<
"eta2:" << m_eta2 <<
' ';
881 s <<
"variant:" << m_variant <<
' ';
882 s <<
"topology:" << m_neighb_type <<
' ';
883 if( m_neighb_type == 2 || m_neighb_type == 4 )
884 s <<
"topology param.:" << m_neighb_param <<
' ';
boost::shared_ptr< base > base_ptr
Alias for shared pointer to base algorithm.
std::vector< double > decision_vector
Decision vector type.
Particle Swarm optimization generational with racing.
Fixed number of iterations.
fitness_vector cur_f
Current fitness vector.
pso_generational_racing(int gen=1, double omega=0.7298, double eta1=2.05, double eta2=2.05, double vcoeff=0.5, int variant=5, int neighb_type=2, int neighb_param=4, unsigned int nr_eval_per_x=5, unsigned int max_fevals=std::numeric_limits< unsigned int >::max())
Constructor.
const individual_type & get_individual(const size_type &) const
Get constant reference to individual at position n.
void register_population(const population &)
Update the population on which the race will run.
const int vonNeumann_neighb_diff[4][2]
Von Neumann neighborhood (increments on particles' lattice coordinates that produce the coordinates o...
Fixed number of function evaluations.
size_type get_dimension() const
Return global dimension.
bool compare_fitness(const fitness_vector &, const fitness_vector &) const
Compare fitness vectors.
std::string human_readable_extra() const
Extra human readable algorithm info.
void evolve(population &) const
Evolve implementation.
size_type get_i_dimension() const
Return integer dimension.
fitness_vector best_f
Best fitness vector so far.
std::vector< double > fitness_vector
Fitness vector type.
c_size_type get_c_dimension() const
Return global constraints dimension.
decision_vector cur_v
Current velocity vector.
const decision_vector & get_ub() const
Upper bounds getter.
Base Stochastic Optimization Problem.
container_type::size_type size_type
Population size type.
decision_vector cur_x
Current decision vector.
rng_uint32 m_urng
Random number generator for unsigned integer values.
f_size_type get_f_dimension() const
Return fitness dimension.
std::string get_name() const
Algorithm name.
const decision_vector & get_lb() const
Lower bounds getter.
rng_double m_drng
Random number generator for double-precision floating point values.
decision_vector best_x
Best decision vector so far.
decision_vector::size_type size_type
Problem's size type: the same as pagmo::decision_vector's size type.
base_ptr clone() const
Clone method.
Racing mechanism for a population.
void set_seed(unsigned int)
Set a new racing seed.
std::vector< fitness_vector > get_mean_fitness(const std::vector< population::size_type > &active_set=std::vector< population::size_type >()) const
Returns mean fitness of the individuals based on past evaluation data.
void inherit_memory(const race_pop &)
Inherits the memory of another race_pop object.