package multinomad.tools;

import java.util.ArrayList;

import multinomad.individuals.DoubleIndividual;
import multinomad.individuals.Population;

public class LoisFunction extends Function {
	
//	args = sciargs();
//
//
//	LOWER_BOUND    ( 0.1  0.1  0.1  20    -90    -80    -90    -90   -90 1     1    -30 )
//	UPPER_BOUND    ( 30 30 30 140 -2 30 10 10 10 30 30 -1)
//	vecV=[-110:10:50];
//	Inf=[-68.6 -49.5 -18.2 -5.06 2.19 3.37 2.52 2.68 5.97 14.6 33.4 60.2 85 114 152 208 254]
//
//	function y=xinf(V,V12,k)
//	    y=1 ./(1+exp((V12-V) ./k));
//	endfunction
//
//	// Fonction coût pour un modèle de type 2-1
//	function e=W21(pa)
//	    e=0;
//	    for i=1:length(vecV)
//	        e=e+(Inf(i)-(pa(1)*xinf(vecV(i),pa(7),pa(10))*(vecV(i)-pa(4))+pa(2)*xinf(vecV(i),pa(8),pa(11))*xinf(vecV(i),pa(9),pa(12))*(vecV(i)-pa(5))+pa(3)*(vecV(i)-pa(6))))^2
//	    end
//	endfunction
//
//	i = 6 
//	pa=[strtod(args(i)) strtod(args(i+1)) strtod(args(i+2)) strtod(args(i+3)) strtod(args(i+4)) strtod(args(i+5)) strtod(args(i+6)) strtod(args(i+7)) strtod(args(i+8)) strtod(args(i+9)) strtod(args(i+10)) strtod(args(i+11))];
//
//	[e]=W21(pa);
	
	double[] lowerbounds = {0.1, 0.1, 0.1, 20, -90, -80, -90, -90, -90, 1, 1, -30};
	double[] upperbounds = {30, 30, 30, 140, -2, 30, 10, 10, 10, 30, 30, -1};
	double[] vecV = {-110,-100,-90,-80,-70,-60,-50,-40,-30,-20,-10,0,10,20,30,40,50};
	double[] inf = {-68.6, -49.5, -18.2, -5.06, 2.19, 3.37, 2.52, 2.68, 5.97, 14.6, 33.4, 60.2, 85, 114, 152, 208, 254};
	
	public LoisFunction() {
		super();
		dimension=12;
		bounds = new ArrayList<ClosedInterval.Double >();
		noOptima = 50;
		for(int i=0;i<dimension;i++) {
			ClosedInterval.Double newBound = new ClosedInterval.Double(lowerbounds[i],upperbounds[i]);
			bounds.add(newBound);
		}
	}
	
	private double xinf(double v, double v12,double k) {
		return  1.0 / (1 + Math.exp((v12-v) / k));
	}

	@Override
	// Fonction coût pour un modèle de type 2-1
	public double evaluate(double[] x) {
		nEvals++;
		double e = 0;
		
		for (int i=0;i<vecV.length;i++) {
			double aux = inf[i]-(x[0]*xinf(vecV[i],x[6],x[9])*(vecV[i]-x[3])+x[1]*xinf(vecV[i],x[7],x[10])*xinf(vecV[i],x[8],x[11])*(vecV[i]-x[4])+x[2]*(vecV[i]-x[5]));
			e+= Math.pow(aux, 2);
		}
		//Transforming the minimization into a maximization problem by multiplying by -1
		return -e;
	}

	@Override
	public double[] evaluateAPopulation(Population pop) {
		//Fitness value to calculate
		double [] fitnesses = new double[pop.size()];
				
		int i = 0;
		for(DoubleIndividual ind: pop) {
			fitnesses[i] = evaluate(ind.getChr().asdouble());
			ind.setFitness(fitnesses[i]);
			i++;
		}
				
		return fitnesses;
	}

	@Override
	public Seeds how_many_goptima(Population p, double accuracy) {
		// TODO Auto-generated method stub
		return null;
	}

}
