package gannuOP.algorithms.particle_swarm;
import gannuOP.algorithms.Optimizer;
import gannuOP.testing.Function;
import gannuOP.testing.Report;
import java.util.ArrayList;
public class LocalBest extends Optimizer {
@Override
public ArrayList<Report> solve(String parameters, Function fx,
double maxFes, double reportFes, double precision) throws Exception {
int P=0;
double error;
int best;
double m=0.0;
int nb=1;
double c1=0.0;
double c2=0.0;
ArrayList<Report>reports=new ArrayList<Report>((int)Math.ceil(maxFes/reportFes));
//Loading parameters
String split[]=parameters.split(",");
for(String parameter:split)
{
if(parameter.startsWith("P="))
{
P=Integer.parseInt(parameter.replace("P=", ""));
}
if(parameter.startsWith("NB="))
{
nb=Integer.parseInt(parameter.replace("NB=", ""));;
}
if(parameter.startsWith("M="))
{
m=Double.parseDouble(parameter.replace("M=", ""));
}
if(parameter.startsWith("C1="))
{
c1=Double.parseDouble(parameter.replace("C1=", ""));
}
if(parameter.startsWith("C2="))
{
c2=Double.parseDouble(parameter.replace("C2=", ""));
}
}
int nbi=(int)Math.ceil(P/nb);
//Initialization of population
ArrayList<double []> pop=new ArrayList<double []>(P);
ArrayList<double []> pbest=new ArrayList<double []>(P);
ArrayList<double []> V=new ArrayList<double []>(P);
for(int i=0;i<P;i++)
{
double []X=new double[fx.getD()+1];
double []xpb=new double[fx.getD()+1];
double []y=new double[fx.getD()];
for(int j=0;j<fx.getD();j++)
{
X[j]=Optimizer.rndreal(fx.getLimit()[0][j], fx.getLimit()[1][j]);
y[j]=Optimizer.rndreal(-Math.abs(fx.getLimit()[1][j]-fx.getLimit()[0][j]), Math.abs(fx.getLimit()[1][j]-fx.getLimit()[0][j]));
xpb[j]=X[j];
}
X[fx.getD()]=fx.evaluate(X,precision);
xpb[fx.getD()]=X[fx.getD()];
pop.add(X);
pbest.add(xpb);
V.add(y);
}
ArrayList<double []> lbest=new ArrayList<double []>(nb);
for(int z=0;z<nb;z++)
{
int k=rnd(0,nbi-1);
double []X=new double[fx.getD()+1];
double []Y=pop.get(z*nbi+k);
for(int j=0;j<(fx.getD()+1);j++)
{
X[j]=Y[j];
}
lbest.add(X);
}
best=Optimizer.getBestIndividual(pop);
error=pop.get(best)[fx.getD()];
int cont=1;
double fes;
double rp=0.0;
for(fes=(double)P;fes<maxFes&&error>=precision;fes+=(double)P)
{
//Recalculate pbest
for(int i=0;i<P;i++)
{
double X[]=pop.get(i);
double pb[]=pbest.get(i);
if(X[fx.getD()]<pb[fx.getD()])
{
for(int j=0;j<fx.getD()+1;j++)
{
pb[j]=X[j];
}
}
}
//Search for lbest
for(int z=0;z<nb;z++)
{
double Y[]=lbest.get(z);
for(int k=0;k<nbi;k++)
{
double X[]=pop.get(z*nbi+k);
if(X[fx.getD()]<Y[fx.getD()])
{
for(int j=0;j<fx.getD()+1;j++)
{
Y[j]=X[j];
}
}
}
}
//Particle flight
for(int i=0,k=0,z=0;i<P;i++,k++)
{
if(k==nbi)
{
k=0;
z++;
}
double X[]=pop.get(i);
double v[]=V.get(i);
double pb[]=pbest.get(i);
double lb[]=lbest.get(z);
for(int j=0;j<fx.getD();j++)
{
double vv=0.0;
do{
vv=Optimizer.rndreal(0.0, 1.0)*v[j]
+c1*Optimizer.rndreal(0.0, 1.0)*(pb[j]-X[j])
+c2*Optimizer.rndreal(0.0, 1.0)*(lb[j]-X[j]);
}while(!fx.isValid(X[j]+vv, j));
v[j]=vv;
X[j]+=v[j];
}
}
//Mutation
if(fes/maxFes<=m)
{
for(int i=0;i<P;i++)
{
double x[]=pop.get(i);
for(int j=0;j<fx.getD();j++)
{
double M;
do
{
if(Optimizer.rndreal(0.0, 1.0)>0.5f)
{
M=(fx.getLimit()[1][j]-x[j])*(1.0-(double)Math.pow(Optimizer.rndreal(0.0, 1.0),1.0-(double)Math.pow(fes/maxFes,5.0)));
}
else
{
M=-(x[j]-fx.getLimit()[1][j])*(1.0-(double)Math.pow(Optimizer.rndreal(0.0, 1.0),1.0-(double)Math.pow(fes/maxFes,5.0)));
}
M+=x[j];
}
while(!fx.isValid(M, j));
x[j]=M;
}
}
}
for(int i=0;i<P;i++)
pop.get(i)[fx.getD()]=fx.evaluate(pop.get(i),precision);
cont++;
if(error>pop.get(Optimizer.getBestIndividual(pop))[fx.getD()])
{
best=Optimizer.getBestIndividual(pop);
error=pop.get(best)[fx.getD()];
}
rp+=(double)P;
if(rp>=reportFes)
{
rp=0.0;
reports.add(new Report(pop, best, fes));
}
}
reports.add(new Report(pop, best, fes));
return reports;
}
}