/*********************************************************************
 * This file is part of the cpplibs suite.
 *
 * Copyright (C) 2001 Topi Mäenpää
 * All rights reserved.
 *
 * This program is free software. You can redistribute and/or modify
 * it under the terms of the free software licence found in the
 * accompanying file "COPYING". The licence terms must always be
 * redistributed with this source file. The above copyright notice
 * must be reproduced in all modified and unmodified copies of this
 * source file.
 *
 * $Revision: 1.3 $
 *********************************************************************/

#ifndef _INDIVIDUAL_H
#define _INDIVIDUAL_H

#include <List.h>

namespace prapi { namespace ga {
	/**
	 * Gene is a representation for a list of "synthetic base pairs"
	 * that constitute up a single gene in a genotype.
	 **/
	template <class T=double> class Gene : public util::List<T>
	{
	public:
		/**
		 * Create a gene with the given initial capacity and block size.
		 **/
		Gene(int capacity=16, int blockSize=16) : util::List<T>(capacity,blockSize) {}
		/**
		 * Copy a gene.
		 **/
		Gene(const Gene& other) : util::List<T>(other) {}
		/**
		 * Copy a gene.
		 **/
		Gene& operator= (const Gene& other) { util::List<T>::operator= (other); return *this; }
	};

	/**
	 * An Individual consists of a sequence of genes, i.e. the genotype,
	 * and a couple of other properties like fitness and age. The reason
	 * why an Individual consists of a list of genes instead of a single
	 * list of values is that crossing over can only occur between
	 * genes. If genes were handled as a one-dimesional sequence, one
	 * had to figure out some un-userfriendly ways to define borders for
	 * genes.
	 **/
	template <class T=double> class Individual : public util::List<Gene<T> >
	{
	public:
		/**
		 * Create a new individual with fitness and age set to zero.
		 **/
		Individual() : age(0), fitness(0) {}
		/**
		 * Create a new individual with the given list as its genotype and
		 * fitness and age set to zero.
		 **/
		Individual(const util::List<Gene<T> >& other) : util::List<Gene<T> >(other), age(0), fitness(0) {}
		/**
		 * Create a copy of another individual.
		 **/
		Individual(const Individual& other) : util::List<Gene<T> >(other), age(other.age), fitness(other.fitness) {}
		/**
		 * Create a new individual with the given genes. This constructor
		 * assumes that each value in <i>values</i> represents one gene.
		 * That is, each gene is represented by a single value. A gene is
		 * created for each value and appended to the internal genotype of
		 * this individual.
		 **/
		Individual(const util::List<T>& values);

		/**
		 * Copy the contents of another individual.
		 **/
		Individual& operator= (const Individual& other);

		template <class U> friend bool operator< (const Individual<U>& i1, const Individual<U>& i2) { return i1.fitness < i2.fitness; }
		template <class U> friend bool operator> (const Individual<U>& i1, const Individual<U>& i2) { return i1.fitness > i2.fitness; }
		template <class U> friend bool operator<= (const Individual<U>& i1, const Individual<U>& i2) { return i1.fitness <= i2.fitness; }
		template <class U> friend bool operator>= (const Individual<U>& i1, const Individual<U>& i2) { return i1.fitness >= i2.fitness; }
		
		/**
		 * The age of an individual.
		 **/
		int age;
		/**
		 * The fitness of an individual.
		 **/
		double fitness;
	};

	template <class T> Individual<T>::Individual(const util::List<T>& values) :
		age(0), fitness(0)
	{
		for (int i=0;i<values.getLength();i++)
			{
				Gene<T> gene(1);
				gene += values[i];
				addElement(gene);
			}
	}

	template <class T> Individual<T>& Individual<T>::operator= (const Individual<T>& other)
	{
		util::List<Gene<T> >::operator= (other);
		age = other.age;
		fitness = other.fitness;
		return *this;
	}

}}

#endif
