#ifndef __POPULATION_H_
#define __POPULATION_H_

#include "Definitions.h"
#include "Random.h"
#include <list>
#include <boost/dynamic_bitset.hpp>
#include <boost/multi_array.hpp>
#include <boost/noncopyable.hpp>

class Population : boost::noncopyable {
  private:
    typedef boost::multi_array<FloatType, 2> MatrixType;
    static const FloatType limitProbabilityMin, limitProbabilityMax;

    MatrixType *data;
    boost::dynamic_bitset<> convergedAlleles;
    std::list<unsigned int> recentConvergedAlleles;

    AlleleType getRandomAllele( unsigned int locus, Random *random ) const;
    AlleleType getProportionateAllele( unsigned int locus, Random *random ) const ;
    AlleleType getConvergedAllele( unsigned int locus ) const;
    void adjustProbabilities( const AlleleType *chromosome, FloatType epsilon );
    void convergeAllele( unsigned int locus );
    void divergeAllele( unsigned int locus );
    void resizeRecentConvergedAlleles( unsigned int c, unsigned int x );

  public:
    Population();
    virtual ~Population();
    void selectIndividual( AlleleType *destination ) const;
    void rewardGenes( const AlleleType *chromosome );
    void penalizeGenes( const AlleleType *chromosome );
    void processConvergedAllele( unsigned int locus, AlleleType allele );
    unsigned int prepareAllelesMessage( MessagePayloadType *buffer );
    void print() const;
};

#endif /* __POPULATION_H_ */
