package gannuOP.algorithms.micro;
import gannuOP.algorithms.Optimizer;
import gannuOP.testing.Function;
import gannuOP.testing.Report;
import java.util.ArrayList;
public class ElitisticEvolution 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 B=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("B="))
{
B=Double.parseDouble(parameter.replace("B=", ""));
}
}
//Initialization of population
ArrayList<double []> pop=new ArrayList<double []>(P);
ArrayList<double []> union=new ArrayList<double []>(P*2);
ArrayList<double []> U=new ArrayList<double []>(P);
for(int i=0;i<P;i++)
{
double []X=new double[fx.getD()+1];
for(int j=0;j<fx.getD();j++)
{
X[j]=Optimizer.rndreal(fx.getLimit()[0][j], fx.getLimit()[1][j]);
}
X[fx.getD()]=fx.evaluate(X,precision);
pop.add(X);
double []y=new double[fx.getD()+1];
U.add(y);
union.add(new double[fx.getD()+1]);
union.add(new double[fx.getD()+1]);
}
double fes;
double []b=new double[fx.getD()];
double []xbest=new double[fx.getD()+1];
for(int j=0;j<fx.getD();j++)
b[j]=B;
int c=1;
best=Optimizer.getBestIndividual(pop);
for(int j=0;j<fx.getD()+1;j++)
{
xbest[j]=pop.get(best)[j];
}
error=pop.get(best)[fx.getD()];
double r=0.0;
for(fes=(double)P;fes<maxFes&&error>=precision;fes+=(double)P)
{
int i=0;
for(i=0;i<P;i++)
{
for(int j=0;j<fx.getD();j++)
{
if(Optimizer.rndreal(0.0,1.0)<=((double)Optimizer.rnd(1, fx.getD())/(double)fx.getD()))
{
double u=0.0;
do
{
u=pop.get(i)[j]+Optimizer.rndreal(-b[j], b[j])*(fx.getLimit()[1][j]-fx.getLimit()[0][j]);
}
while(!fx.isValid(u, j));
U.get(i)[j]=u;
}
else
{
U.get(i)[j]=pop.get(i)[j];
}
}
}
for(i=0;i<P;i++)
{
int k=Optimizer.rnd(0, P-c);
int l=Optimizer.rnd(0, P-c);
int m=Optimizer.rnd(0, P-1);
double c1=Optimizer.rndreal(0.0, 1.0);
double c2=Optimizer.rndreal(0.0, 1.0-c1);
double c3=1.0-c1-c2;
for(int j=0;j<fx.getD();j++)
{
U.get(i)[j]=c1*U.get(k)[j]+c2*pop.get(l)[j]+c3*U.get(m)[j];
}
U.get(i)[fx.getD()]=fx.evaluate(U.get(i),precision);
for(int j=0;j<fx.getD()+1;j++)
{
union.get(i*2)[j]=pop.get(i)[j];
union.get(i*2+1)[j]=U.get(i)[j];
}
}
//Replacement
for(i=0;i<c;i++)
{
int sel=i;
for(int z=i+1;z<P;z++)
{
if(union.get(sel)[fx.getD()]>union.get(z)[fx.getD()])
{
sel=z;
}
}
double aux;
for(int j=0;j<fx.getD()+1&&i!=sel;j++)
{
aux=union.get(sel)[j];
union.get(sel)[j]=union.get(i)[j];
union.get(i)[j]=aux;
}
}
for(i=0;i<c;i++)
{
for(int j=0;j<fx.getD()+1;j++)
{
pop.get(i)[j]=union.get(i)[j];
}
}
for(i=c;i<P;i++)
{
int k=Optimizer.rnd(0, P-1);
for(int j=0;j<fx.getD()+1;j++)
{
pop.get(i)[j]=U.get(k)[j];
}
}
//Recalculation of adaptive parameters
if(error>pop.get(Optimizer.getBestIndividual(pop))[fx.getD()])
{
best=Optimizer.getBestIndividual(pop);
error=pop.get(best)[fx.getD()];
}
if(Math.abs(error-xbest[fx.getD()])<=precision*0.001)
{
if(c>1)
c--;
for(int j=0;j<fx.getD();j++)
{
b[j]=Math.abs((pop.get(best)[j]-xbest[j])/(fx.getLimit()[1][j]-fx.getLimit()[0][j]));
}
}
else
{
if(c<P)
{
c++;
}
for(int j=0;j<fx.getD();j++)
{
b[j]=Optimizer.rndreal(0.0, b[j]);
}
}
for(int j=0;j<fx.getD();j++)
{
if(b[j]==0.0)
{
b[j]=B*(1.0-Optimizer.rndreal(0.0, 1.0)*fes/maxFes);
}
}
for(int j=0;j<fx.getD()+1;j++)
{
xbest[j]=pop.get(best)[j];
}
r+=(double)P;
if(r>=reportFes)
{
r=0.0;
reports.add(new Report(pop, best, fes));
}
}
reports.add(new Report(pop, best, fes));
return reports;
}
}