
#include "stdafx.h"
#include "Dif_evol.h"

	void Diferencialni::init()
	{
		if (data!=nullptr)
		{
			for (int i=0;i<NP;i++)
				delete(data[i]);
			delete(data);
			delete(Zkusebni);

		}
		data = new double*[NP];
		Zkusebni = new double[D+1];
		Meze = new double*[D];
		for (int i=0;i<D;i++)
		{
			Meze[i]= new double[2];
			Meze[i][0]=-1;
			Meze[i][1]=1;
		}
		for (int i=0;i<NP;i++)
		data[i] = new double[D+1];
	}

	Diferencialni::~Diferencialni()
	{
		for (int i=0;i<NP;i++)
			delete data[i];
		delete data;
		delete Zkusebni;
		
	}

	
	void Diferencialni::Start_Evoluce()
	{
		for (int i=0;i<NP;i++)
		{
			for (int k=0;k<D;k++)
			{
				data[i][k]=((Meze[k][1]-Meze[k][0])*rand()/(RAND_MAX*1.0)+Meze[k][0]);
			}
		data[i][D]= Fitness(data[i]);
		}
		changed = false;

	}

	void Diferencialni::Reprodukce()
	{
		
		if (changed) Start_Evoluce();
		for (int i=0;i<NP;i++)
		{
			int X[3];
			do
			for (int k=0;k<3;k++)
			{
				X[k]=(((NP-1)*rand()-1)/RAND_MAX);
				if ((X[k]>=i)||(X[k]<0))
					X[k]++;
			}
			while((X[0]==X[1])||(X[0]==X[2])||X[1]==X[2]);

			for (int k=0;k<D;k++)
			{
				if (((double)rand()/(double)RAND_MAX)<CR)
				{
					Zkusebni[k]=F*(data[X[0]][k]-data[X[1]][k])+data[X[2]][k];
					if ((Zkusebni[k]<Meze[k][0])||(Zkusebni[k]>Meze[k][1]))
						Zkusebni[k]=((Meze[k][1]-Meze[k][0])*(double)rand()/(RAND_MAX*1.0)+Meze[k][0]);
				}
				else
					Zkusebni[k]=data[i][k];
			}

			Zkusebni[D]=Fitness(Zkusebni);
			if (Zkusebni[D]<data[i][D])
			{
				double* help = data[i];
				data[i]=Zkusebni;
				Zkusebni = help;
			}

			
		}
	
	
	}



	double Diferencialni::Fitness(double* A)
	{
		double x=0;
		for (int i=0;i<(D);i++)
//			x+=(A[i]*A[i]-A[i+1]*A[i+1])+(1-A[i])*(1-A[i]);
			x+=A[i]*A[i]-10*cos(2*3.14159265358979323846*A[i]);
		return x;
	}
	void Diferencialni::Elita(double* A)
	{
		double max = data[0][D];
		int max_i = 0;
		for (int i=0;i<NP;i++)
			if (data[i][D]<max)
			{
				max = data[i][D];
				max_i = i;
			}
		for (int i=0;i<D+1;i++)
		A[i] = data[max_i][i];
	}
void Diferencialni::SetD(int A) {			
			for (int i=0;i<D;i++)
				delete(Meze[i]);
			delete(Meze);
			D = A;
			init();
			changed = true;
	}

void Diferencialni::SetNP(int A) {
			if (A==NP) return;
			double** X = new double*[A];
			if (A<NP)
				for (int i=0;i<A;i++)
					X[i]=data[i];
			else
			{
				for (int i=0;i<NP;i++)
					X[i]=data[i];
				for (int i=NP;i<A;i++)
				{	
					X[i] = new double[D+1];
					for (int k=0;k<D;k++)
						X[i][k]=((Meze[k][1]-Meze[k][0])*rand()/(RAND_MAX*1.0)+Meze[k][0]);
		
					X[i][D]= Fitness(X[i]);
				}

			}
			delete data;
			data = X;
			NP = A;
			
}

double Diferencialni::HodnotaElita()  {
		double max = data[0][D];
		for (int i=0;i<NP;i++)
			if (data[i][D]<max)
			{
				max = data[i][D];
			}

		return max;
}

double Diferencialni::StandartDeviation()
{
	double prum = 0;
	for (int i=0;i<NP;i++)
		prum+= data[i][D];
	prum = prum / NP;
	double Sum = 0;
	for (int i=0;i<NP;i++)
		Sum += (data[i][D]-prum)*(data[i][D]-prum);
	return (sqrt(Sum/(NP-1)));
}

//}
