/*
 * Individual.java 2003/03/15
 *
 *
*/


/*
 * An individual in the genetic algorithm's population. Needs to
 * provide storage and management of chromosome, fitness, and
 * objective function values
 *
 */
public class Individual implements Comparable, java.io.Serializable {

    /* 
     * Stores this individual's non-negative fitness.
     */
    public double fitness;

    /* 
     * Stores this individual's objective function value.
     */
    public double objectiveFunction;

    /* 
     * Stores this individual's chromosome
     */
    public int[] chromosome;

    /*
     * Individual's chromosome length
     */
    public int chromosomeLength;


    /*
     * Application data structure interface to store application
     * specific information in an individual. This is currently an
     * empty interface since it is application specific, the
     * application should specify its implementation. This just allows
     * the information to be carried around with an individual.
     */
    public ApplicationInformation appInfo;

    /*
     * Constructs an individual of given chromosome length. Initializes 
     * chromosome randomly.
     *
     * @param len the length of the chromosome to be allocated.
     */
    public Individual(int len){
	allocate(len);
    }
    
    /*
     * Constructs a new individual by copying another individual.
     *
     * @param ip is the individual to copy
     */

    public Individual(Individual ip){
	this.fitness = ip.fitness;
	this.objectiveFunction = ip.objectiveFunction;
	this.chromosomeLength = ip.chromosomeLength;

	this.chromosome = new int[this.chromosomeLength];

	for(int i = 0; i < this.chromosomeLength; i++){
	    this.chromosome[i] = ip.chromosome[i];
	}
    }

    private void allocate(int len){
	this.chromosome = new int[len];
	for(int i = 0; i < len; i++){
	    this.chromosome[i] = GARandom.flip(0.5);
	}
    }

    /**
     * Implements the Comparable interface. Since we want Individuals to
     * be sorted from biggest fitness to smallest fitness, we return
     * a negative, 0, or positive integer according to whether this 
     * Individual's fitness is GREATER than, equal to, or LESS than 
     * the other individual's fitness.
     *
     * @param o an object of type {@link Individual}.
     */
    public int compareTo(Object o) {
	Individual other = (Individual) o;
	if (fitness > other.fitness) {
	    return -1;
	} else if (fitness < other.fitness) {
	    return 1;
	} else {
	    return 0;
	}
    } 

    /*
     * Calculates the hamming distance between this individual and the
     * argument. This assumes that chromosome lengths are equal
     * @param ip the other individual.
     *
     * @return the distance between ip and this individual
     */
    public int hammingDistance(Individual ip){
	int otherLen = ip.chromosomeLength;
	if(otherLen != this.chromosomeLength){
	    System.err.println("This version of cigar does not support "
			       + "unequal length chromosomes ");
	    System.exit(1);
	}
	int distance = 0;
	for(int i = 0; i < this.chromosomeLength; i++){
	    distance += (this.chromosome[i] == ip.chromosome[i] ? 0 : 1);
	}
	return distance;
    }

	    

}
