#include "gadget.h" //All the required standard header files are in here
#include "optinfo.h"
#include "mathfunc.h"
#include "doublevector.h"
#include "intvector.h"
#include "errorhandler.h"
#include "ecosystem.h"
#include "global.h"
#include "pso.h"
#include <float.h>
#ifdef _OPENMP
#include "omp.h"
#endif
extern Ecosystem* EcoSystem;
#ifdef _OPENMP
extern Ecosystem** EcoSystems;
#endif
//==============================================================
//// calulate swarm size based on dimensionality
int OptInfoPso::pso_calc_swarm_size(int dim) {
int size = 10. + 2. * sqrt(dim);
return (size > PSO_MAX_SIZE ? PSO_MAX_SIZE : size);
}
void OptInfoPso::OptimiseLikelihood() {
handle.logMessage(LOGINFO, "\nStarting PSO optimisation algorithm\n");
double bestf, tmp;
int i, offset, rchange, rcheck, rnumber;
int nvars = EcoSystem->numOptVariables();
DoubleVector x(nvars);
// DoubleVector trialx(nvars);
DoubleVector bestx(nvars);
DoubleVector lowerb(nvars);
DoubleVector upperb(nvars);
DoubleVector init(nvars);
//DoubleVector initialstep(nvars, rho);
IntVector param(nvars, 0);
IntVector lbound(nvars, 0);
IntVector rbounds(nvars, 0);
IntVector trapped(nvars, 0);
/**
* Internal variables for PSO
*/
// printf("nvars:%d\n",nvars);
if (size == 0) size = pso_calc_swarm_size(nvars);
DoubleMatrix pos(size, nvars, 0.0); // position matrix
DoubleMatrix vel(size, nvars, 0.0); // velocity matrix
DoubleMatrix pos_b(size, nvars, 0.0); // best position matrix
DoubleVector fit(size); // particle fitness vector
DoubleVector fit_b(size); // best fitness vector
DoubleMatrix pos_nb(size, nvars, 0.0); // what is the best informed position for each particle
IntMatrix comm(size, size, 0); // communications:who informs who rows : those who inform cols : those who are informed
int improved; // whether solution->error was improved during the last iteration
int d, step;
double a, b;
double rho1, rho2; //random numbers (coefficients)
double w; //current omega
Inform_fun inform_fun;
Calc_inertia_fun calc_inertia_fun; // inertia weight update function
int psosteps = 0;
if (seed == 0) seed = 1234;
handle.logMessage(LOGINFO, "Starting PSO with particles ", size, "\n");
// SELECT APPROPRIATE NHOOD UPDATE FUNCTION
switch (nhood_strategy) {
case PSO_NHOOD_GLOBAL:
// comm matrix not used
handle.logMessage(LOGINFO, "PSO will use global communication\n");
inform_fun = &OptInfoPso::inform_global;
break;
case PSO_NHOOD_RING:
handle.logMessage(LOGINFO, "PSO will use ring communication\n");
init_comm_ring(comm);
inform_fun = &OptInfoPso::inform_ring;
break;
case PSO_NHOOD_RANDOM:
handle.logMessage(LOGINFO, "PSO will use random communication\n");
init_comm_random(comm);
inform_fun = &OptInfoPso::inform_random;
break;
}
// SELECT APPROPRIATE INERTIA WEIGHT UPDATE FUNCTION
switch (w_strategy) {
case PSO_W_CONST:
handle.logMessage(LOGINFO, "PSO will use constant inertia\n");
calc_inertia_fun = &OptInfoPso::calc_inertia_const;
break;
case PSO_W_LIN_DEC:
handle.logMessage(LOGINFO, "PSO will use linear decreasing inertia\n");
calc_inertia_fun = &OptInfoPso::calc_inertia_lin_dec;
break;
}
//
//initialize omega using standard value
//
w = PSO_INERTIA;
handle.logMessage(LOGINFO, "PSO initial inertia ", w, "\n");
handle.logMessage(LOGINFO, "PSO c1", c1, "\n");
handle.logMessage(LOGINFO, "PSO c2", c2, "\n");
handle.logMessage(LOGINFO, "PSO goal", goal, "\n");
// if (scale)
EcoSystem->scaleVariables();
//#ifdef _OPENMP
// int numThr = omp_get_max_threads ( );
//#pragma omp parallel for
// for (i=0;i<numThr;i++)
// EcoSystems[i]->scaleVariables();
//#endif
EcoSystem->getOptScaledValues(x);
EcoSystem->getOptLowerBounds(lowerb);
EcoSystem->getOptUpperBounds(upperb);
EcoSystem->getOptInitialValues(init);
for (i = 0; i < nvars; ++i) {
bestx[i] = x[i];
param[i] = i;
}
//se escala?
// if (scale)
for (i = 0; i < nvars; i++) {
// Scaling the bounds, because the parameters are scaled
lowerb[i] = lowerb[i] / init[i];
upperb[i] = upperb[i] / init[i];
if (lowerb[i] > upperb[i]) {
tmp = lowerb[i];
lowerb[i] = upperb[i];
upperb[i] = tmp;
}
}
bestf = EcoSystem->SimulateAndUpdate(x);
if (bestf != bestf) { //check for NaN
handle.logMessage(LOGINFO, "Error starting PSO optimisation with f(x) = infinity");
converge = -1;
iters = 1;
return;
}
offset = EcoSystem->getFuncEval(); //number of function evaluations done before loop
// newf = bestf;
// oldf = bestf;
iters = 0;
//
// Initialize the particles
//
i = 0;
handle.logMessage(LOGINFO, "Initialising PSO ", size, "particles\n");
// SWARM INITIALIZATION
//
// Initialize the fist particle with the best known position
//
for (d = 0; d < nvars; d++) {
// generate two numbers within the specified range and around trialx
a = x[d];
// initialize position
pos[i][d] = a;
pos_b[i][d] = a;
pos_nb[i][d] = a;
// a = lowerb[d] + (upperb[d] - lowerb[d]) * (rand() * 1.0 / RAND_MAX);
b = lowerb[d] + (upperb[d] - lowerb[d]) * (rand_r(&seed) * 1.0 / RAND_MAX);
vel[i][d] = (a - b) / 2.;
}
fit[i] = EcoSystem->SimulateAndUpdate(pos[i]);
fit_b[i] = fit[i]; // this is also the personal best
if (fit[i] < bestf) {
bestf = fit[i];
bestx = pos[i];
}
// Now other particles with a random position in the solution space
//
//#pragma omp parallel for default(shared) private(i,d,a,b)
for (i = 1; i < size; i++) {
ostringstream spos, svel;
spos << "Initial position of particle " << i << " [";
svel << "Initial velocity of particle " << i << " [";
// for each dimension
for (d = 0; d < nvars; d++) {
// generate two numbers within the specified range and around trialx
a = lowerb[d] + (upperb[d] - lowerb[d]) * (rand_r(&seed) * 1.0 / RAND_MAX);
b = lowerb[d] + (upperb[d] - lowerb[d]) * (rand_r(&seed) * 1.0 / RAND_MAX);
// initialize position
pos[i][d] = a;
// best position is trialx
pos_b[i][d] = a;
pos_nb[i][d] = a;
// initialize velocity
vel[i][d] = (a - b) / 2.;
spos << pos[i][d] << " ";
svel << vel[i][d] << " ";
}
//#ifdef _OPENMP
// fit[i] = EcoSystems[omp_get_thread_num ()]->SimulateAndUpdate(pos[i]);
//#else
fit[i] = EcoSystem->SimulateAndUpdate(pos[i]);
//#endif
fit_b[i] = fit[i]; // this is also the personal best
// update gbest??
//#pragma omp critical (best1)
if (fit[i] < bestf) {
// update best fitness
bestf = fit[i];
// copy particle pos to gbest vector
//memmove((void *)&bestx, (void *)&pos[i],
// sizeof(double) * nvars);
bestx = pos[i];
}
spos << " ]";
svel << " ]";
handle.logMessage(LOGDEBUG, spos.str().c_str());
handle.logMessage(LOGDEBUG, svel.str().c_str());
}
//
// RUN ALGORITHM
//
psosteps = 0;
while (1) {
handle.logMessage(LOGINFO, "PSO optimisation after", psosteps * size, "\n");
if (isZero(bestf)) {
iters = EcoSystem->getFuncEval() - offset;
handle.logMessage(LOGINFO, "Error in PSO optimisation after", iters, "function evaluations, f(x) = 0");
converge = -1;
return;
}
/* if too many function evaluations occur, terminate the algorithm */
iters = EcoSystem->getFuncEval() - offset;
if (psosteps > psoiter) {
handle.logMessage(LOGINFO, "\nStopping PSO optimisation algorithm\n");
handle.logMessage(LOGINFO, "The optimisation stopped after", iters, "function evaluations");
handle.logMessage(LOGINFO, "The optimisation stopped because the maximum number of PSO steps was reached");
handle.logMessage(LOGINFO, "was reached and NOT because an optimum was found for this run");
score = EcoSystem->SimulateAndUpdate(bestx);
for (i = 0; i < nvars; i++)
bestx[i] = bestx[i] * init[i];
handle.logMessage(LOGINFO, "\nPSO finished with a likelihood score of", score);
EcoSystem->storeVariables(score, bestx);
return;
}
// update inertia weight
if (w_strategy) w = (this->*calc_inertia_fun)(psosteps);
// check optimization goal
if (bestf <= goal) {
handle.logMessage(LOGINFO, "\nStopping PSO optimisation algorithm\n");
handle.logMessage(LOGINFO, "Goal achieved!!! @ step ", psosteps);
score = EcoSystem->SimulateAndUpdate(bestx);
handle.logMessage(LOGINFO, "\nPSO finished with a likelihood score of", score);
break;
}
// update pos_nb matrix (find best of neighborhood for all particles)
(this->*inform_fun)(comm, pos_nb, pos_b, fit_b, bestx, improved);
// the value of improved was just used; reset it
improved = 0;
// update all particles
//#pragma omp parallel for private(d,rho1,rho2) default(shared)
for (i = 0; i < size; i++) {
// handle.logMessage(LOGDEBUG, "In parallel",omp_get_thread_num(),"\n");
ostringstream spos, svel;
spos << "New position of particle " << i << " [";
svel << "New velocity of particle " << i << " [";
// for each dimension
for (d = 0; d < nvars; d++) {
// calculate stochastic coefficients
rho1 = c1 * (rand_r(&seed) * 1.0) / RAND_MAX;
rho2 = c2 * (rand_r(&seed) * 1.0) / RAND_MAX;
// update velocity
vel[i][d] = w * vel[i][d] + rho1 * (pos_b[i][d] - pos[i][d]) + rho2 * (pos_nb[i][d] - pos[i][d]);
// update position
pos[i][d] += vel[i][d];
spos << pos[i][d] << " ";
svel << vel[i][d] << " ";
// clamp position within bounds?
if (clamp_pos) {
if (pos[i][d] < lowerb[d]) {
pos[i][d] = lowerb[d];
vel[i][d] = 0;
}
else if (pos[i][d] > upperb[d]) {
pos[i][d] = upperb[d];
vel[i][d] = 0;
}
}
else {
// enforce periodic boundary conditions
if (pos[i][d] < lowerb[d]) {
pos[i][d] = upperb[d] - fmod(lowerb[d] - pos[i][d], upperb[d] - lowerb[d]);
vel[i][d] = 0;
}
else if (pos[i][d] > upperb[d]) {
pos[i][d] = lowerb[d] + fmod(pos[i][d] - upperb[d], upperb[d] - lowerb[d]);
vel[i][d] = 0;
}
}
} //end for nvars
spos << "]" << endl;
svel << "]" << endl;
handle.logMessage(LOGDEBUG, spos.str().c_str());
handle.logMessage(LOGDEBUG, svel.str().c_str());
// update particle fitness
// fit[i] = EcoSystems[omp_get_thread_num()]->SimulateAndUpdate(pos[i]);
fit[i] = EcoSystem->SimulateAndUpdate(pos[i]);
// update personal best position?
if (fit[i] < fit_b[i]) {
fit_b[i] = fit[i];
pos_b[i] = pos[i];
}
// update gbest??
handle.logMessage(LOGDEBUG, "Particle ", i);
handle.logMessage(LOGDEBUG, "The likelihood score is", bestf, "at the point");
handle.logMessage(LOGDEBUG, "Its likelihood score is", fit[i], "at the point");
//#pragma omp critical (best2)
if (fit[i] < bestf) {
improved = 1;
// update best fitness
bestf = fit[i];
for (d = 0; d < nvars; d++)
bestx[d] = pos[i][d] * init[d];
iters = EcoSystem->getFuncEval() - offset;
handle.logMessage(LOGINFO, "\nNew optimum found after", iters, "function evaluations");
handle.logMessage(LOGINFO, "The likelihood score is", bestf, "at the point");
EcoSystem->storeVariables(bestf, bestx);
EcoSystem->writeBestValues();
bestx = pos[i];
}
} // end i
psosteps++;
} // while (newf < bestf)
iters = EcoSystem->getFuncEval() - offset;
handle.logMessage(LOGINFO, "Existing PSO after ", iters, "function evaluations ...");
for (d = 0; d < nvars; d++)
bestx[d] = bestx[d] * init[d];
EcoSystem->storeVariables(bestf, bestx);
EcoSystem->writeBestValues();
}
#ifdef _OPENMP
void OptInfoPso::OptimiseLikelihoodREP() {
OptimiseLikelihood();
}
void OptInfoPso::OptimiseLikelihoodOMP() {
handle.logMessage(LOGINFO, "\nStarting PSO optimisation algorithm\n");
double tmp;
int i, offset, rchange, rcheck, rnumber;
int nvars = EcoSystem->numOptVariables();
DoubleVector x(nvars);
// DoubleVector trialx(nvars);
DoubleVector bestx(nvars);
DoubleVector scalex(nvars);
DoubleVector lowerb(nvars);
DoubleVector upperb(nvars);
DoubleVector init(nvars);
//DoubleVector initialstep(nvars, rho);
IntVector param(nvars, 0);
IntVector lbound(nvars, 0);
IntVector rbounds(nvars, 0);
IntVector trapped(nvars, 0);
struct Best { double bestf; int index;};
struct Best best;
/**
* Internal variables for PSO
*/
// printf("nvars:%d\n",nvars);
if (size == 0) size = pso_calc_swarm_size(nvars);
DoubleMatrix pos(size, nvars, 0.0); // position matrix
DoubleMatrix vel(size, nvars, 0.0); // velocity matrix
DoubleMatrix pos_b(size, nvars, 0.0); // best position matrix
DoubleVector fit(size); // particle fitness vector
DoubleVector fit_b(size); // best fitness vector
DoubleMatrix pos_nb(size, nvars, 0.0); // what is the best informed position for each particle
IntMatrix comm(size, size, 0); // communications:who informs who rows : those who inform cols : those who are informed
int improved; // whether solution->error was improved during the last iteration
int d, step;
double a, b;
double rho1, rho2; //random numbers (coefficients)
double w; //current omega
Inform_fun inform_fun;
Calc_inertia_fun calc_inertia_fun; // inertia weight update function
int psosteps = 0; //!= iters?
// if (seed == 0) seed = 1234;
handle.logMessage(LOGINFO, "Starting PSO with particles ", size, "\n");
// SELECT APPROPRIATE NHOOD UPDATE FUNCTION
switch (nhood_strategy) {
case PSO_NHOOD_GLOBAL:
// comm matrix not used
handle.logMessage(LOGINFO, "PSO will use global communication\n");
inform_fun = &OptInfoPso::inform_global;
break;
case PSO_NHOOD_RING:
handle.logMessage(LOGINFO, "PSO will use ring communication\n");
init_comm_ring(comm);
inform_fun = &OptInfoPso::inform_ring;
break;
case PSO_NHOOD_RANDOM:
handle.logMessage(LOGINFO, "PSO will use random communication\n");
init_comm_random(comm);
inform_fun = &OptInfoPso::inform_random;
break;
}
// SELECT APPROPRIATE INERTIA WEIGHT UPDATE FUNCTION
switch (w_strategy) {
case PSO_W_CONST:
handle.logMessage(LOGINFO, "PSO will use constant inertia\n");
calc_inertia_fun = &OptInfoPso::calc_inertia_const;
break;
case PSO_W_LIN_DEC:
handle.logMessage(LOGINFO, "PSO will use linear decreasing inertia\n");
calc_inertia_fun = &OptInfoPso::calc_inertia_lin_dec;
break;
}
//
//initialize omega using standard value
//
w = PSO_INERTIA;
handle.logMessage(LOGINFO, "PSO initial inertia ", w, "\n");
handle.logMessage(LOGINFO, "PSO c1", c1, "\n");
handle.logMessage(LOGINFO, "PSO c2", c2, "\n");
handle.logMessage(LOGINFO, "PSO goal", goal, "\n");
EcoSystem->scaleVariables();
int numThr = omp_get_max_threads ( );
// if (scale) {
#pragma omp parallel for
for (i=0;i<numThr;i++)
EcoSystems[i]->scaleVariables();
// }
//#endif
EcoSystem->getOptScaledValues(x);
EcoSystem->getOptLowerBounds(lowerb);
EcoSystem->getOptUpperBounds(upperb);
EcoSystem->getOptInitialValues(init);
for (i = 0; i < nvars; ++i) {
bestx[i] = x[i];
param[i] = i;
}
//se escala?
// if (scale)
for (i = 0; i < nvars; i++) {
scalex[i] = x[i];
// Scaling the bounds, because the parameters are scaled
lowerb[i] = lowerb[i] / init[i];
upperb[i] = upperb[i] / init[i];
if (lowerb[i] > upperb[i]) {
tmp = lowerb[i];
lowerb[i] = upperb[i];
upperb[i] = tmp;
}
}
best.bestf = EcoSystem->SimulateAndUpdate(x);
best.index=0;
if (best.bestf != best.bestf) { //check for NaN
handle.logMessage(LOGINFO, "Error starting PSO optimisation with f(x) = infinity");
converge = -1;
iters = 1;
return;
}
offset = EcoSystem->getFuncEval(); //number of function evaluations done before loop
// newf = bestf;
// oldf = bestf;
iters = 0;
//
// Initialize the particles
//
i = 0;
handle.logMessage(LOGINFO, "Initialising PSO ", size, "particles\n");
// SWARM INITIALIZATION
//
// Initialize the fist particle with the best known position
//
// best.bestf=bestf;
for (d = 0; d < nvars; d++) {
// generate two numbers within the specified range and around trialx
a = x[d];
// initialize position
pos[i][d] = a;
pos_b[i][d] = a;
pos_nb[i][d] = a;
// a = lowerb[d] + (upperb[d] - lowerb[d]) * (rand() * 1.0 / RAND_MAX);
b = lowerb[d] + (upperb[d] - lowerb[d]) * (rand_r(&seed) * 1.0 / RAND_MAX);
vel[i][d] = (a - b) / 2.;
}
fit[i] = EcoSystem->SimulateAndUpdate(pos[i]);
fit_b[i] = fit[i]; // this is also the personal best
if (fit[i] < best.bestf) {
best.bestf = fit[i];
// best.bestf=bestf;
bestx = pos[i];
best.index=i;
}
// Now other particles with a random position in the solution space
//
// handle.logMessage(LOGINFO, "ini 1 best.bestf=",best.bestf, "\n");
#pragma omp declare reduction(bestomp: Best : omp_out = omp_in.bestf < omp_out.bestf ? omp_in : omp_out) initializer(omp_priv=omp_orig)
#pragma omp parallel for default(shared) private(i,d,a,b) reduction(bestomp:best) //firstprivate(bestf)
for (i = 1; i < size; i++) {
ostringstream spos, svel;
spos << "Initial position of particle " << i << " [";
svel << "Initial velocity of particle " << i << " [";
// for each dimension
for (d = 0; d < nvars; d++) {
// generate two numbers within the specified range and around trialx
a = lowerb[d] + (upperb[d] - lowerb[d]) * (rand_r(&seed) * 1.0 / RAND_MAX);
b = lowerb[d] + (upperb[d] - lowerb[d]) * (rand_r(&seed) * 1.0 / RAND_MAX);
// initialize position
pos[i][d] = a;
// best position is trialx
pos_b[i][d] = a;
pos_nb[i][d] = a;
// initialize velocity
vel[i][d] = (a - b) / 2.;
spos << pos[i][d] << " ";
svel << vel[i][d] << " ";
}
//#ifdef _OPENMP
fit[i] = EcoSystems[omp_get_thread_num ()]->SimulateAndUpdate(pos[i]);
// best.bestf = fit[i];
//#else
// fit[i] = EcoSystem->SimulateAndUpdate(pos[i]);
//#endif
fit_b[i] = fit[i]; // this is also the personal best
// update gbest??
//#pragma omp critical (best1)
if (fit[i] < best.bestf) {
// update best fitness
// bestf = fit[i];
// copy particle pos to gbest vector
//memmove((void *)&bestx, (void *)&pos[i],
// sizeof(double) * nvars);
// bestx = pos[i];
best.index=i;
// bestf=best.bestf;
best.bestf = fit[i];
}
spos << " ]";
svel << " ]";
handle.logMessage(LOGDEBUG, spos.str().c_str());
handle.logMessage(LOGDEBUG, svel.str().c_str());
}
//
// Compare the reduction with the best value
//
// if (best.bestf < bestf){
// bestx=pos[best.index];
// bestf=best.bestf;
// }
//
// RUN ALGORITHM
//
// handle.logMessage(LOGINFO, "ini 2 best.bestf=",best.bestf, "\n");
psosteps = 0;
while (1) {
handle.logMessage(LOGINFO, "PSO optimisation after", psosteps * size, "\n");
if (isZero(best.bestf)) {
iters = (EcoSystems[0]->getFuncEval() * numThr) + EcoSystem->getFuncEval() - offset;
handle.logMessage(LOGINFO, "Error in PSO optimisation after", iters, "function evaluations, f(x) = 0");
converge = -1;
return;
}
/* if too many function evaluations occur, terminate the algorithm */
iters = (EcoSystems[0]->getFuncEval() * numThr) + EcoSystem->getFuncEval() - offset;
if (psosteps > psoiter) {
handle.logMessage(LOGINFO, "\nStopping PSO optimisation algorithm\n");
handle.logMessage(LOGINFO, "The optimisation stopped after", iters, "function evaluations");
handle.logMessage(LOGINFO, "The optimisation stopped because the maximum number of PSO steps was reached");
handle.logMessage(LOGINFO, "was reached and NOT because an optimum was found for this run");
score = EcoSystem->SimulateAndUpdate(bestx);
for (i = 0; i < nvars; i++)
bestx[i] = bestx[i] * init[i];
handle.logMessage(LOGINFO, "\nPSO finished with a likelihood score of", score);
EcoSystem->storeVariables(score, bestx);
return;
}
// update inertia weight
if (w_strategy) w = (this->*calc_inertia_fun)(psosteps);
// check optimization goal
if (best.bestf <= goal) {
handle.logMessage(LOGINFO, "\nStopping PSO optimisation algorithm\n");
handle.logMessage(LOGINFO, "Goal achieved!!! @ step ", psosteps);
score = EcoSystem->SimulateAndUpdate(bestx);
handle.logMessage(LOGINFO, "\nPSO finished with a likelihood score of", score);
break;
}
// update pos_nb matrix (find best of neighborhood for all particles)
(this->*inform_fun)(comm, pos_nb, pos_b, fit_b, bestx, improved);
// the value of improved was just used; reset it
improved = 0;
// update all particles
// best.bestf=bestf;
//#pragma omp declare reduction(bestomp2: Best : omp_out = omp_in.bestf < omp_out.bestf ? omp_in : omp_out) initializer(omp_priv=omp_orig)
#pragma omp parallel for default(shared) private(i,d,rho1,rho2) reduction(bestomp:best) //firstprivate(best)
for (i = 0; i < size; i++) {
// handle.logMessage(LOGDEBUG, "In parallel",omp_get_thread_num(),"\n");
ostringstream spos, svel;
spos << "New position of particle " << i << " [";
svel << "New velocity of particle " << i << " [";
// for each dimension
for (d = 0; d < nvars; d++) {
// calculate stochastic coefficients
rho1 = c1 * (rand_r(&seed) * 1.0) / RAND_MAX;
rho2 = c2 * (rand_r(&seed) * 1.0) / RAND_MAX;
// update velocity
vel[i][d] = w * vel[i][d] + rho1 * (pos_b[i][d] - pos[i][d]) + rho2 * (pos_nb[i][d] - pos[i][d]);
// update position
pos[i][d] += vel[i][d];
spos << pos[i][d] << " ";
svel << vel[i][d] << " ";
// clamp position within bounds?
if (clamp_pos) {
if (pos[i][d] < lowerb[d]) {
pos[i][d] = lowerb[d];
vel[i][d] = 0;
}
else if (pos[i][d] > upperb[d]) {
pos[i][d] = upperb[d];
vel[i][d] = 0;
}
}
else {
// enforce periodic boundary conditions
if (pos[i][d] < lowerb[d]) {
pos[i][d] = upperb[d] - fmod(lowerb[d] - pos[i][d], upperb[d] - lowerb[d]);
vel[i][d] = 0;
}
else if (pos[i][d] > upperb[d]) {
pos[i][d] = lowerb[d] + fmod(pos[i][d] - upperb[d], upperb[d] - lowerb[d]);
vel[i][d] = 0;
}
}
} //end for nvars
spos << "]" << endl;
svel << "]" << endl;
handle.logMessage(LOGDEBUG, spos.str().c_str());
handle.logMessage(LOGDEBUG, svel.str().c_str());
// update particle fitness
fit[i] = EcoSystems[omp_get_thread_num()]->SimulateAndUpdate(pos[i]);
// fit[i] = EcoSystem->SimulateAndUpdate(pos[i]);
// update personal best position?
// best.bestf = fit[i];
if (fit[i] < fit_b[i]) {
fit_b[i] = fit[i];
pos_b[i] = pos[i];
}
// update gbest??
handle.logMessage(LOGDEBUG, "Particle ", i);
handle.logMessage(LOGDEBUG, "The likelihood score is", best.bestf, "at the point");
handle.logMessage(LOGDEBUG, "Its likelihood score is", fit[i], "at the point");
//#pragma omp critical (best2)
if (fit[i] < best.bestf) {
improved = 1;
// update best fitness
best.index=i;
best.bestf = fit[i];
for (d = 0; d < nvars; d++)
bestx[d] = pos[i][d] * init[d];
iters = (EcoSystems[0]->getFuncEval() * numThr) + EcoSystem->getFuncEval() - offset;
handle.logMessage(LOGINFO, "\nNew optimum found after", iters, "function evaluations");
handle.logMessage(LOGINFO, "The likelihood score is", best.bestf, "at the point");
EcoSystem->storeVariables(best.bestf, bestx);
EcoSystem->writeBestValues();
bestx = pos[i];
}
} // end i
// if (best.bestf < bestf){
// bestf=best.bestf;
// bestx=pos[best.index];
// for (d = 0; d < nvars; d++)
// bestx[d] = bestx[d] * init[d];
// iters = EcoSystem->getFuncEval() - offset; //To change. It is incorrect when is parallel.
// handle.logMessage(LOGINFO, "\nNew optimum found after", iters, "function evaluations");
// handle.logMessage(LOGINFO, "The likelihood score is", bestf, "at the point");
// EcoSystem->storeVariables(bestf, bestx);
// EcoSystem->writeBestValues();
// bestx=pos[best.index];
// }
// handle.logMessage(LOGINFO, "best.bestf=",best.bestf, "\n");
psosteps += numThr;
} // while (newf < bestf)
iters = (EcoSystems[0]->getFuncEval() * numThr) + EcoSystem->getFuncEval() - offset;
handle.logMessage(LOGINFO, "Existing PSO after ", iters, "function evaluations ...");
for (d = 0; d < nvars; d++)
bestx[d] = bestx[d] * init[d];
EcoSystem->storeVariables(best.bestf, bestx);
EcoSystem->writeBestValues();
}
#endif
/**
* \brief calculate constant inertia weight equal to w_max
*/
double OptInfoPso::calc_inertia_const(int step) {
return w_max;
}
/**
* \brief calculate linearly decreasing inertia weight
*/
double OptInfoPso::calc_inertia_lin_dec(int step) {
int dec_stage = 3 * psoiter / 4;
if (step <= dec_stage)
return w_min + (w_max - w_min) * (dec_stage - step) / dec_stage;
else
return w_min;
}
/**
* \brief NEIGHBORHOOD (COMM) MATRIX STRATEGIES. global neighborhood
*/
void OptInfoPso::inform_global(IntMatrix& comm, DoubleMatrix& pos_nb, DoubleMatrix& pos_b, DoubleVector& fit_b, DoubleVector& gbest, int improved) {
int i;
// all particles have the same attractor (gbest)
// copy the contents of gbest to pos_nb
for (i = 0; i < size; i++)
//memmove((void *)&pos_nb[i][0], &gbest[0],
// sizeof(double) * gbest.Size());
pos_nb[i] = gbest;
}
/**
* \brief general inform function :: according to the connectivity matrix COMM, it copies the best position (from pos_b) of the informers of each particle to the pos_nb matrix
*/
void OptInfoPso::inform(IntMatrix& comm, DoubleMatrix& pos_nb, DoubleMatrix& pos_b, DoubleVector& fit_b, int improved) {
int i, j;
int b_n; // best neighbor in terms of fitness
// for each particle
for (j = 0; j < size; j++) {
b_n = j; // self is best
// who is the best informer??
for (i = 0; i < size; i++)
// the i^th particle informs the j^th particle
if (comm[i][j] && fit_b[i] < fit_b[b_n])
// found a better informer for j^th particle
b_n = i;
// copy pos_b of b_n^th particle to pos_nb[j]
//memmove((void *)&pos_nb[j][0],
// (void *)&pos_b[b_n][0],
// sizeof(double) * pos_nb.Ncol(j));
pos_nb[j] = pos_b[b_n];
}
}
/**
* \brief topology initialization :: this is a static (i.e. fixed) topology
*/
void OptInfoPso::init_comm_ring(IntMatrix& comm) {
int i;
// reset array
comm.setToZero();
// choose informers
for (i = 0; i < size; i++) {
// set diagonal to 1
comm[i][i] = 1;
if (i == 0) {
// look right
comm[i][1] = 1;
// look left
comm[i][size - 1] = 1;
}
else if (i == size - 1) {
// look right
comm[i][0] = 1;
// look left
comm[i][i - 1] = 1;
}
else {
// look right
comm[i][i + 1] = 1;
// look left
comm[i][i - 1] = 1;
}
}
// Print Matrix
handle.logMessage(LOGDEBUG, "\nPSO ring communication\n");
for (i = 0; i < size; i++) {
string message = "[";
for (int j = 0; j < size; j++) {
std::ostringstream ss;
ss << comm[i][j];
message = message + " " + ss.str();
}
message = message + "]\n";
handle.logMessage(LOGDEBUG, message.c_str());
}
}
void OptInfoPso::inform_ring(IntMatrix& comm, DoubleMatrix& pos_nb, DoubleMatrix& pos_b, DoubleVector& fit_b, DoubleVector& gbest, int improved) {
// update pos_nb matrix
inform(comm, pos_nb, pos_b, fit_b, improved);
}
/**
* \brief random neighborhood topology
*/
void OptInfoPso::init_comm_random(IntMatrix& comm) {
int i, j, k;
// reset array
comm.setToZero();
// choose informers
for (i = 0; i < size; i++) {
// each particle informs itself
comm[i][i] = 1;
// choose kappa (on average) informers for each particle
for (k = 0; k < nhood_size; k++) {
// generate a random index
//j = gsl_rng_uniform_int(settings->rng, settings->size);
j = rand_r(&this->seed) * size / RAND_MAX;
// particle i informs particle j
comm[i][j] = 1;
}
}
}
void OptInfoPso::inform_random(IntMatrix& comm, DoubleMatrix& pos_nb, DoubleMatrix& pos_b, DoubleVector& fit_b, DoubleVector& gbest, int improved) {
// regenerate connectivity??
if (!improved) init_comm_random(comm);
inform(comm, pos_nb, pos_b, fit_b, improved);
}