package multinomad.tools;

import java.util.ArrayList;

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

public class LoisFunctionBench extends Function {
	

	

	double[] lowerbounds = {0.1, 0.1, 0.1, 20, -90, -80, -90, -90, -90, -90, 1,  -30, 1,  -30};
	double[] upperbounds = {30,  30,  30,  150, -2,  30,  -2,  -2,  -2,  -2,  30, -1,  30, -1};
	double[] vecV = {-110,-100,-90,-80,-70,-60,-50,-40,-30,-20,-10,0,10,20,30,40,50};
	// Benchmark parameters
	double gCa=0.4; 	double  gK=0.9;		double gL=0.24;
	double ECa=126.5; 	double EK=-86;		double EL=-49;
	double V12x1=-4.3;	double V12x2=-13.01;double V12x3=-51.7; double V12x4=-82.2;
	double kx1=22.8; 	double kx2=-29.9; 	double kx3=10.8;	double kx4=-3.3;
	
	public LoisFunctionBench() {
		super();
		dimension=14;
		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));
	}
	
	private double iinf(double vh) {
		double y = gCa*xinf(vh,V12x1,kx1)*xinf(vh,V12x2,kx2)*(vh-ECa)+gK*xinf(vh,V12x3,kx3)*xinf(vh,V12x4,kx4)*(vh-EK)+gL*(vh-EL);
		return y;
	}

	@Override
	// Fonction coût pour un modèle W
	public double evaluate(double[] x) {
		nEvals++;
		double e = 0;

		for (int i=0;i<vecV.length;i++) {
			double aux = iinf(vecV[i])-(x[0]*xinf(vecV[i],x[6],x[10]))*xinf(vecV[i],x[7],x[11])*(vecV[i]-x[3])+x[1]*xinf(vecV[i],x[8],x[12])*xinf(vecV[i],x[9],x[13])*(vecV[i]-x[4])+x[2]*(vecV[i]-x[5]);
			e+= Math.pow(aux, 2);
		}
		double y = (e*1.0)/vecV.length;		//Transforming the minimization into a maximization problem by multiplying by -1
		return -y;
	}

	@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;
	}

}
