/* ========================================================================== *
 *  Multi-population genetic algorithm.
 *
 *  Author: Firas Safadi (fsafadi@ulg.ac.be)
 * ========================================================================== */

#pragma once

#include "EvolutionaryAlgorithm.h"

class GeneticAlgorithm : public EvolutionaryAlgorithm
{
public:
  typedef enum {OnePoint, Uniform, Mixed, Random} CrossoverType;

  //Constructor
  GeneticAlgorithm(nat popCount, nat popSize, nat genSize, nat maxGenSize);
  //Destructor
  ~GeneticAlgorithm();

  //Spawns populations using unique per population genetics
  void hatchSpecies();
  //Evolves each population according to its own genetics
  void evolveSpecies();
  //Wipes all populations
  void wipeSpecies();
  //(Re)Spawns all populations after setting new genome size
  void hatchSpecies(nat genSize);

  //Sets the genetics of a specific population
  void setPopGenetics(nat i, real infBound, real supBound, real expInfBound, real expSupBound, real eliteProp, real breedProp, real mutantProp, real mutationRate, real mutationGamma, CrossoverType xoType);

  //Sets the genetics of the species
  void setSpeciesGenetics(
    real infBoundLow, real infBoundHigh, real supBoundLow, real supBoundHigh,
    real expInfBoundLow, real expInfBoundHigh, real expSupBoundLow, real expSupBoundHigh,
    real elitePropLow, real elitePropHigh, real breedPropLow, real breedPropHigh, real mutantPropLow, real mutantPropHigh,
    real mutationRateLow, real mutationRateHigh,
    real mutationGammaLow, real mutationGammaHigh,
    CrossoverType xoType
  );

  //Displays the genetics of each population
  void dispGenetics() const;

  //Displays the genetics of a population
  void dispGenetics(nat i) const;

protected:
  Matrix m_pInfBoundVec;
  Matrix m_pSupBoundVec;

  Matrix m_pExpInfBoundVec;
  Matrix m_pExpSupBoundVec;

  Matrix m_pEliteProportionVec;
  Matrix m_pBreedProportionVec;
  Matrix m_pMutantProportionVec;

  Natrix m_pEliteVec;
  Natrix m_pBreedVec;
  Natrix m_pMutantVec;

  Natrix m_pXoTypeVec;

  Matrix m_pMutationRateVec;
  Matrix m_pMutationGammaVec;

  Interval m_pInfBoundRange;
  Interval m_pSupBoundRange;

  Interval m_pExpInfBoundRange;
  Interval m_pExpSupBoundRange;

  Interval m_pEliteProportionRange;
  Interval m_pBreedProportionRange;
  Interval m_pMutantProportionRange;

  Interval m_pMutationRateRange;
  Interval m_pMutationGammaRange;

  CrossoverType m_eXoType;

private:
  //Validates the genetics of the species
  void validateGenetics();
  //Validates the genetics of a population
  void validatePopGenetics(nat i);
  //Generates the genetics of all populations on host
  void generateSpecies();
  //Copies the genetics of the species to device
  void pushSpeciesToDevice();
};
