Skip to content
This repository has been archived by the owner on Jul 16, 2024. It is now read-only.

Add hexagonal topology to pso #148

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 49 additions & 2 deletions src/algorithm/pso.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ pso::pso(int gen, double omega, double eta1, double eta2, double vcoeff, int var
pagmo_throw(value_error,"algorithm variant must be one of 1 ... 6");
}

if (neighb_type < 1 || neighb_type > 4) {
pagmo_throw(value_error,"swarm topology variant must be one of 1 ... 4");
if (neighb_type < 1 || neighb_type > 5) {
pagmo_throw(value_error,"swarm topology variant must be one of 1 ... 5");
}
// And neighb param???
}
Expand Down Expand Up @@ -177,6 +177,7 @@ void pso::evolve(population &pop) const
switch( m_neighb_type ){
case 1: initialize_topology__gbest( pop, best_neighb, best_fit, neighb ); break;
case 3: initialize_topology__von( neighb ); break;
case 5: initialize_topology__hexagonal(neighb);break;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not the index order (1,3,4,5) ?
Two spaces after colon

case 4: initialize_topology__adaptive_random( neighb );
best_fit = pop.champion().f; // need to track improvements in best found fitness, to know when to rewire
break;
Expand Down Expand Up @@ -380,6 +381,7 @@ decision_vector pso::particle__get_best_neighbor( population::size_type pidx, st
case 2: // { lbest }
case 3: // { von }
case 4: // { adaptive random }
case 5: // {hexagonal}
default:
// iterate over indexes of the particle's neighbours, and identify the best
bnidx = neighb[pidx][0];
Expand Down Expand Up @@ -565,6 +567,51 @@ void pso::initialize_topology__adaptive_random( std::vector< std::vector<int> >
}


/**
* @brief Arranges particles in a 2D lattice with alternatively staggered rows, where each interacts with its 6 nearest neighbours.

*/
const int hexagonal_neighb_diff_even[6][2] = { {-1,-1}, {0,-1}, {-1,0}, {1,0}, {-1,1}, {0,1} };
const int hexagonal_neighb_diff_odd[6][2] = { {0,-1}, {1,-1}, {-1,0}, {1,0}, {0,1}, {1,1} };

void pso::initialize_topology__hexagonal( std::vector< std::vector<int> > &neighb ) const
{
int swarm_size = neighb.size();
int cols, rows; // lattice structure

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case there's no reason to align variable names in the column with multiple spaces, use a single space.

In this method you're using 8 spaces for indentation. We try to stick with tabs for C++ and 4 spaces for Python code.

int pidx, nidx; // particle and neighbour indices, in the swarm and neighbourhood vectors
int p_x, p_y; // particle's coordinates in the lattice
int n_x, n_y; // particle neighbor's coordinates in the lattice

rows = std::sqrt( swarm_size );
while( ( (swarm_size % rows != 0) || (rows % 2 == 1)) && (rows>1) )

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spaces around operator >. You have an extra space before last parenthesis. I suggest installing some C++/Python coding style checker.

rows -= 1;
if (rows<2)
pagmo_throw(value_error,"Hexagonal topology requires a swarm size to have an even factor > 2");
cols = swarm_size / rows;

for( pidx = 0; pidx < swarm_size; pidx++ ){
p_x = pidx % cols;
p_y = pidx / cols;

for( nidx = 0; nidx < 6; nidx++ ){
if (p_y % 2 == 0){
n_x = ( p_x + hexagonal_neighb_diff_even[nidx][0] ) % cols;
n_y = ( p_y + hexagonal_neighb_diff_even[nidx][1] ) % rows;
}
else {
n_x = ( p_x + hexagonal_neighb_diff_odd[nidx][0] ) % cols;
n_y = ( p_y + hexagonal_neighb_diff_odd[nidx][1] ) % rows;
}

if( n_x < 0 ) n_x = cols + n_x; // sign of remainder(%) in a division when at least one of the operands is negative is compiler implementation specific. The 'if' here ensures the same behaviour across compilers
if( n_y < 0 ) n_y = rows + n_y;

neighb[pidx].push_back( n_y * cols + n_x );
}
}
}



/// Algorithm name
std::string pso::get_name() const
Expand Down
1 change: 1 addition & 0 deletions src/algorithm/pso.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ class __PAGMO_VISIBLE pso: public base
void initialize_topology__lbest( std::vector< std::vector<int> > &neighb ) const;
void initialize_topology__von( std::vector< std::vector<int> > &neighb ) const;
void initialize_topology__adaptive_random( std::vector< std::vector<int> > &neighb ) const;
void initialize_topology__hexagonal( std::vector< std::vector<int> > &neighb ) const;
std::string get_name() const;
protected:
std::string human_readable_extra() const;
Expand Down