package com.z_PEA;

import com.z_PEA.Individual;
import com.z_PEA.Problem;


// NOTE: Use derived class RandomPopulation to generate the hBOA initial population.
// NOTE: Use constructor Population() to generate empty populations.

public class Population{
	protected int N;                   			// Size for each population, in particular for SelectedSet (NS).
	public Individual[] individuals; 			// Population of N char[] of size xSize.
	protected int worstPos, bestPos;			// Position of Worst and Best individuals. computeFitnessValues() is responsible for computing these positions.
	protected double avgFit, worstFit, bestFit;	// Worst and Best fitnesses. computeFitnessValues() is responsible for computing these fitnesses.
	protected double[] fitness;          		// Array of N fitness values.	
	protected int[] uniFrequencies;				// Array of xSize univariate frequencies.
	
	public Population(int otherN){
		this.N = otherN;
		individuals = new Individual[otherN];
		for(int i = 0; i < individuals.length; i++)
			individuals[i] = new Individual();
		fitness = new double[otherN];
	}
	
	public int                      getN(){return this.N;}
	public   Individual[] getIndividuals(){return individuals;}
	public Individual getIndividual(int i){return individuals[i];}
	public               int getWorstPos(){return worstPos;}
	public                int getBestPos(){return bestPos;}
	public              double getAvgFit(){return avgFit;}
	public            double getWorstFit(){return worstFit;}
	public             double getBestFit(){return bestFit;}
	public           double[] getFitness(){return fitness;}
	public        double getFitness(int i){return fitness[i];}
	public       int[] getUniFrequencies(){return uniFrequencies;}
	public    int getUniFrequencies(int j){return uniFrequencies[j];}
	
	public void    setWorstPos(int wPos){worstPos = wPos;}
	public void     setBestPos(int bPos){bestPos  = bPos;}
	public void setWorstFit(double wFit){worstFit = wFit;}
	public void  setBestFit(double bFit){bestFit  = bFit;}
	
	public void setIndividual(int position, Individual johnDoe, double fit){
		individuals[position] = johnDoe;
		fitness[position] = fit;
	}
	
	public Individual getIndividualCopy(int i){						// NOTE: Non shallow copy!
		Individual indiv = new Individual();
		for(int j = 0; j < Problem.n; j++)
			indiv.setAllele(j, individuals[i].getAllele(j));
		return indiv;
	}
	
	public void computeFitnessValues(){
		worstFit = Double.MAX_VALUE;
		bestFit  = Double.MIN_VALUE;
		for(int i = 0; i < this.N; i++){
			double newFit = individuals[i].computeFitness();
			fitness[i] = newFit;
			if(newFit < worstFit){									// The current individual is also the worst.
				worstPos = i;										// Update information about the worst individual.
				worstFit = newFit;
			}
			if(newFit > bestFit){									// The current individual is also the best.
				bestPos = i;										// Update information about the best individual.
				bestFit = newFit;
			}			
		}
	}
	
	public double computeAvgFitness(){
		double sumFit =  0;
		for(int i = 0; i < this.N; i++)
			sumFit += fitness[i];	
		avgFit = (double)sumFit/((double)this.N);
		return avgFit;
	}
	
	////////////////////////////////////////////////////////////
	// Computes the univariate absolute frequencies.
	// Use ((float)uniFrequencies[j])/(float)hBOASolver.N) to
	// compute relative frequencies.
	//
	////////////////////////////////////////////////////////////
	
	public void computeUnivariateFrequencies(){
		uniFrequencies = new int[Problem.n]; 						// NOTE: uniFrequencies is initialized all zeros by default.
		for(int j = 0; j < Problem.n; j++){
			for(int i = 0; i < this.N; i++)
				if(individuals[i].getAllele(j) == '1')
					uniFrequencies[j]++;
		}
	}
	
	public String toString(){
		String str ="";
		for(int i = 0; i < this.N; i++){
			for(int j = 0; j < Problem.n; j++)
				str += individuals[i].getAllele(j);
			str += "\n";

		}
		return str;  // + statistics.printStats();
	}

}// END: super class Population







