Ejemplo n.º 1
0
//-----------------------------------Epoch()-----------------------------
//
//	takes a population of chromosones and runs the algorithm through one
//	cycle.
//	Returns a new population of chromosones.
//-----------------------------------------------------------------------
vector<SGenome> CGenAlg::Epoch(vector<SGenome> &old_pop)
{
	//assign the given population to the classes population
  m_vecPop = old_pop;

  //reset the appropriate variables
  Reset();

  //create a temporary vector to store new chromosones
	vector <SGenome> vecNewPop;

  CalculateBestWorstAvTot();
  
  //sort the population (for scaling and elitism)
  sort(m_vecPop.begin(), m_vecPop.end());


	//Now to add a little elitism we shall add in some copies of the
	//fittest genomes. Make sure we add an EVEN number or the roulette
  //wheel sampling will crash
	if (!(CParams::iNumCopiesElite * CParams::iNumElite % 2))
	{
		GrabNBest(CParams::iNumElite, CParams::iNumCopiesElite, vecNewPop);
	}
	


	  //--------------now to enter the GA loop

	
	//repeat until a new population is generated
	while (vecNewPop.size() < m_iPopSize)
	{

    //select using tournament selection for a change
    SGenome mum = TournamentSelection(CParams::iTournamentCompetitors);
		SGenome dad = TournamentSelection(CParams::iTournamentCompetitors);

		//create some offspring via crossover
		vector<double>		baby1, baby2;

		CrossoverAtSplits(mum.vecWeights, dad.vecWeights, baby1, baby2);

		//now we mutate
		Mutate(baby1);
		Mutate(baby2);

		//now copy into vecNewPop population
		vecNewPop.push_back( SGenome(baby1, 0) );
		vecNewPop.push_back( SGenome(baby2, 0) );
	}

	//finished so assign new pop back into m_vecPop
	m_vecPop = vecNewPop;

	return m_vecPop;
}
Ejemplo n.º 2
0
///////////////////////////////  INTERFACE  ////////////////////////////////
void GeneticClass::Interface(){
	lc = 10000;             
	int algorithmIteration = 30;
	float crossoverRatio = 0.9;
	int mutationIteration = 1000;

	int score = 0, parent1, parent2;

	DrawingPopulation();
	Rating();
	cout << "Rodzice: " << bestScoreInAll << endl;
	checksRepeatsInSet();

	////////////// SELEKCJA I KRZYZOWANIE I MUTACJA///////////////////////////////
	for (int z = 0; z<algorithmIteration; z++){
		int P = -1;		                            // licznik nowej populacji
		vector<bool> crossed(lc,false);
		int crossoverIterations = (lc - 2) * crossoverRatio;
		#pragma omp parallel for
		for (P = -1; P < crossoverIterations; P += 2)
		{
			parent1 = TournamentSelection(10);
			do
				parent2 = TournamentSelection(10);
			while (parent1 == parent2);
			crossed[parent1] = true;
			crossed[parent2] = true;
			Crossover(parent1, parent2, children[P + 1], children[P + 2]);
		}

		for (int i = 0 ; i < lc; i++) {					//Dopisuje do children osobniki ktore nie braly udzialu w krzyzowaniu
			if (crossoverIterations != lc) {
				if (crossed[i] == false) {
					children[crossoverIterations++] = chromosom[i];
				}
			}
			else {
				break;
			}
		}

		chromosom.swap(children);						
		
		for (int i = 0; i<mutationIteration; i++){
			int target = TournamentSelection(100);
			Mutation(chromosom[target]);			//	przy zakomentowanym krzyzowaniu wpisalem tu chromosom zamiast children 
		}

		checksRepeatsInSet();
	
		score = Rating();
		cout << "Populacja_" << z << " = " << score << endl;
	}
	showBest();
}
Ejemplo n.º 3
0
//------------------------Epoch-------------------------------
//
//	creates a new population of genomes using the selection,
//	mutation and crossover operators
//------------------------------------------------------------
void CgaTSP::Epoch()
{

	//first we reset variables and calculate the fitness of each genome
	Reset();
	
	CalculatePopulationsFitness();

	//if we have found a solution exit
	if ((m_dShortestRoute <= m_pMap->BestPossibleRoute()))
	{
		m_bStarted = false;
		
		return;
	}	

  //perform the appropriate fitness scaling
  FitnessScaleSwitch();

  //if sigma is zero (either set in sigma scaling or in CalculateBestWorstAv
  //then the population are identical and we should stop the run
  if (m_dSigma == 0)
  {
    m_bStarted = false;

    return;
  }
	
	//create a temporary vector for the new population
	vector<SGenome> vecNewPop;
	
  if (m_bElitism)
  {
	  //Now to add a little elitism we shall add in some copies of the
	  //fittest genomes
	  const int CopiesToAdd = 2;
	  const int NBest		  = 4;
	  
	  //make sure we add an EVEN number or the roulette wheel
	  //sampling will crash
	  if (!(CopiesToAdd * NBest % 2))
	  {
		  GrabNBest(NBest, CopiesToAdd, vecNewPop);
	  }
  }

  //SUS selection selects the entire population all at once so we have to
  //handle the epoch slightly differently if SUS is chosen
  if(m_SelectionType != SUS)
  {
	  //now create the remainder of the population
	  while (vecNewPop.size() != m_iPopSize)
	  {
	  
		  SGenome mum, dad;
    
      //switch on selection method
      switch(m_SelectionType)
      {
      case ROULETTE:
  
        //grab two parents dependent on the selection method
		    mum = RouletteWheelSelection();
		    dad = RouletteWheelSelection();

        break;

      case TOURNAMENT:

        mum = TournamentSelection(NUM_TO_COMPARE);
	      dad = TournamentSelection(NUM_TO_COMPARE);

        break;

      case ALT_TOURNAMENT:
 
        mum = AlternativeTournamentSelection();
	      dad = AlternativeTournamentSelection();

        break;
      }

		  //create 2 children
		  SGenome baby1, baby2;
		  
		  //Breed them
      Crossover(mum.vecCities,
                dad.vecCities,
                baby1.vecCities,
                baby2.vecCities,
                m_CrossoverType);

		  //and mutate them
		  Mutate(baby1.vecCities, m_MutationType);
		  Mutate(baby2.vecCities, m_MutationType);

		  //add them to new population
		  vecNewPop.push_back(baby1);
		  vecNewPop.push_back(baby2);
	  }
  }

  //SUS selection
  else
  {
    //select all the individuals
    vector<SGenome> vecSampledPop;

    SUSSelection(vecSampledPop);

    //step through the newly sampled population and apply crossover
    //and mutation operators
    for (int gen=0; gen<vecSampledPop.size(); gen+=2)
    {
      SGenome baby1, baby2;
      
      Crossover(vecSampledPop[gen].vecCities,
                vecSampledPop[gen+1].vecCities,
                baby1.vecCities,
                baby2.vecCities,
                m_CrossoverType);

      Mutate(baby1.vecCities, m_MutationType);
      Mutate(baby2.vecCities, m_MutationType);

      vecNewPop.push_back(baby1);
      vecNewPop.push_back(baby2);      

    }
   
  }

	//copy into next generation
	m_vecPopulation = vecNewPop;

	//increment generation counter
	++m_iGeneration;
}
int main() {
  // Declare GA parameters - pop. size, variables, etc
  const int populationSize = 30;
  const int numberOfGenerations = 100;
  const int tournamentSize = 2;
  const double tournamentSelectionParameter = 0.75;
  const float crossOverProbability = 0.7;
  const float creepRateMutation = 0.1;
  const double mutationProbability = 0.05;

  // Vehicle related parameters for chromosome construction
  int numberOfUnits = 4; 			// Including Tractor
  std::vector<int> numberOfAxlesOnEachUnit{3,3,2,3};   // Can be made inputs later
  int numberOfEngines = 3;			// D11, D13, D16
  int numberOfElectricMotors = 3;
  int numberOfElectricBuffers = 3;

  std::vector<int> machineParameters{numberOfEngines, numberOfElectricMotors, numberOfElectricBuffers};
  std::vector<std::vector<int>> vehicleConfigurationParameters{machineParameters, numberOfAxlesOnEachUnit};

  // Initialise the population
  Population population = InitialisePopulation(populationSize, vehicleConfigurationParameters);
  // Check if population is correctly initialised
  std::cout<<"Population initialised"<<std::endl;
  PrintMembersOfPopulation(population);

  // Create files for storing population of each generation & fitnesses of each individual in each generation
  std::fstream populationEachGeneration;
  std::fstream fitnessEachGeneration;   

  //Delete any existing instances of the files to be created
  remove("PopulationEachGeneration.txt");
  remove("FitnessEachGeneration.txt");

  std::vector<double> bestFitnessOverGenerations;

  std::vector<std::vector<double>> missionData;
  LoadMission(missionData);

  // Loop begins - generation evolution start
  for(int generationIndex=0;generationIndex<numberOfGenerations;generationIndex++) {
    std::cout<<"GENERATION NUMBER : "<<generationIndex<<std::endl;
    // Store current population in file PopulationEachGeneration.txt
    //StoreCurrentPopulationInFile(population, populationEachGeneration, rangeAllVariables);

    // Declare variables required for fitness evaluation
    Fitnesses fitness;	// Keep inside scope of each generation
    double tempFitness;     // Keep inside scope of each generation

    // Evaluate the fitness of each member in the population and assign to 'fitness' vector
    fitness = EvaluatePopulationFitness(population, missionData);
    StoreCurrentFitnessInPopulation(fitness, fitnessEachGeneration);

    // Declare variables required for best individual search
    long double maximumFitness;
    int bestIndividualIndex;
    Individual bestIndividual;       

    // Find best individual in the current population
    bestIndividualIndex = GetBestIndividualIndex(fitness); //, population, rangeAllVariables); 
    bestIndividual = population[bestIndividualIndex];
    maximumFitness = fitness[bestIndividualIndex];
    bestFitnessOverGenerations.push_back(maximumFitness);

    //PrintFitness(fitness);
    //std::cout<<"The best Individual is "<<bestIndividualIndex<<std::endl;
    std::cout<<"The optimal function value is "<<maximumFitness<<std::endl;

    // Based on fitness, perform selection & crossover without replacement
    Population tempPopulation;
    tempPopulation = population;

    for(int i=0;i<populationSize;i=i+2) { // i=i+2 since 2 individuals are crossed over
      // Select two random individuals using tournament selection
      std::vector<Individual> individualsToCrossover;  // Both individuals to be crossed over placed in a vector
      for(int j=0;j<tournamentSize;j++) {
        int temporaryIndex=TournamentSelection(fitness, tournamentSelectionParameter, tournamentSize);
        //std::cout<<"Chosen Individual :"<<temporaryIndex<<std::endl;
        individualsToCrossover.push_back(population[temporaryIndex]);
      } // end of Tournament Selection

      // Perform crossover
      // ALGORITHM ONE - INDIVIDUAL UNIT GENE CONSIDERATION FOR CROSSOVER
      std::vector<Individual> crossedOverIndividuals = CrossOver(individualsToCrossover, crossOverProbability);
      tempPopulation[i]=crossedOverIndividuals[0];
      tempPopulation[i+1]=crossedOverIndividuals[1];
	   
      // ALGORITHM TWO - CROSSOVER AT UNIT GENE BOUNDARIES FOR WHOLE INDIVIDUALS
      /*double randomDouble = GetRandomDouble();
      if(randomDouble < crossOverProbability) {
        //std::cout<<"CrossOver Initiated"<<std::endl;
        std::vector<Individual> crossedOverIndividuals = CrossOver(individualsToCrossover);
        tempPopulation[i]=crossedOverIndividuals[0];
        tempPopulation[i+1]=crossedOverIndividuals[1];
      } 
      else {
        // Place original pair of individuals in corresponding (consecutive) locations in tempPopulation
        //std::cout<<"No Crossover"<<std::endl;	
        tempPopulation[i]=individualsToCrossover[0];
        tempPopulation[i+1]=individualsToCrossover[1];
      }  // end of Crossover*/
    } // End of Selection and Crossover

    //std::cout<<std::endl<<"After Crossover"<<std::endl;
    //PrintMembersOfPopulation(tempPopulation);

    // Mutate each individual
    MutatePopulation(tempPopulation, mutationProbability); // Population mutated

    //std::cout<<std::endl<<"After Mutation"<<std::endl;
    //PrintMembersOfPopulation(tempPopulation);

    // Elitism
    tempPopulation[0]=population[bestIndividualIndex];

    for(int i=0;i<tempPopulation.size();i++)
      population[i]=tempPopulation[i];
  } // end of generation loop


  // Declare variables required for final fitness evaluation
  Fitnesses finalFitness;      // Keep inside scope of each generation
  double tempFitness;     // Keep inside scope of each generation

  // Evaluate the fitness of each member in the population and assign to 'fitness' vector
  finalFitness = EvaluatePopulationFitness(population, missionData);
  //PrintFitness(finalFitness);

  // Declare variables required for best individual search
  long double finalMaximumFitness;
  int finalBestIndividualIndex;
  Individual finalBestIndividual;

  // Find best individual in the current population
  finalBestIndividualIndex = GetBestIndividualIndex(finalFitness); //, population, rangeAllVariables); 
  finalBestIndividual = population[finalBestIndividualIndex];
  finalMaximumFitness = finalFitness[finalBestIndividualIndex];

  PrintMembersOfPopulation(population);
  // Check if the best individual is being correctly calculated
  std::cout<<"The best Individual is "<<finalBestIndividualIndex<<std::endl;
  PrintIndividual(population[finalBestIndividualIndex]);
  std::cout<<"The optimal function value is "<<finalMaximumFitness<<std::endl;
  //std::cout<<std::endl;

  std::ofstream fileOperation;
  remove("fitness_vs_generation.txt");
  fileOperation.open("fitness_vs_generation.txt");
  if (fileOperation.is_open()) {
    for(int i=0;i<bestFitnessOverGenerations.size();i++) {
      fileOperation << bestFitnessOverGenerations[i] << '\n';
    }
    fileOperation.close();
  }
}// end of main()
Ejemplo n.º 5
0
//------------------------------------- Epoch ----------------------------
//
//  This function performs one epoch of the genetic algorithm and returns 
//  a vector of pointers to the new phenotypes
//------------------------------------------------------------------------
vector<CNeuralNet*> Cga::Epoch(const vector<double> &FitnessScores)
{
  //first check to make sure we have the correct amount of fitness scores
  if (FitnessScores.size() != m_vecGenomes.size())
  {
    MessageBox(NULL,"Cga::Epoch(scores/ genomes mismatch)!","Error", MB_OK);
  }

  //reset appropriate values and kill off the existing phenotypes and
  //any poorly performing species
  ResetAndKill();

  //update the genomes with the fitnesses scored in the last run
  for (int gen=0; gen<m_vecGenomes.size(); ++gen)
  {
    m_vecGenomes[gen].SetFitness(FitnessScores[gen]);
  }

  //sort genomes and keep a record of the best performers
  SortAndRecord();

  //separate the population into species of similar topology, adjust
  //fitnesses and calculate spawn levels
  SpeciateAndCalculateSpawnLevels();

  //this will hold the new population of genomes
  vector<CGenome> NewPop;

  //request the offspring from each species. The number of children to 
  //spawn is a double which we need to convert to an int. 
  int NumSpawnedSoFar = 0;

  CGenome baby;

  //now to iterate through each species selecting offspring to be mated and 
  //mutated	
  for (int spc=0; spc<m_vecSpecies.size(); ++spc)
  {
    //because of the number to spawn from each species is a double
    //rounded up or down to an integer it is possible to get an overflow
    //of genomes spawned. This statement just makes sure that doesn't
    //happen
    if (NumSpawnedSoFar < CParams::iNumSweepers)
    {
      //this is the amount of offspring this species is required to
      // spawn. Rounded simply rounds the double up or down.
      int NumToSpawn = Rounded(m_vecSpecies[spc].NumToSpawn());

      bool bChosenBestYet = false;

      while (NumToSpawn--)
      {
        //first grab the best performing genome from this species and transfer
        //to the new population without mutation. This provides per species
        //elitism
        if (!bChosenBestYet)
        {         
          baby = m_vecSpecies[spc].Leader();

          bChosenBestYet = true;
        }

        else
        {
          //if the number of individuals in this species is only one
          //then we can only perform mutation
          if (m_vecSpecies[spc].NumMembers() == 1)
          {         
            //spawn a child
            baby = m_vecSpecies[spc].Spawn();
          }

          //if greater than one we can use the crossover operator
          else
          {
            //spawn1
            CGenome g1 = m_vecSpecies[spc].Spawn();

            if (RandFloat() < CParams::dCrossoverRate)
            {

              //spawn2, make sure it's not the same as g1
              CGenome g2 = m_vecSpecies[spc].Spawn();

              //number of attempts at finding a different genome
              int NumAttempts = 5;

              while ( (g1.ID() == g2.ID()) && (NumAttempts--) )
              {  
                g2 = m_vecSpecies[spc].Spawn();
              }

              if (g1.ID() != g2.ID())
              {
                baby = Crossover(g1, g2);
              }
            }

            else
            {
              baby = g1;
            }
          }

          
          ++m_iNextGenomeID;

          baby.SetID(m_iNextGenomeID);

          //now we have a spawned child lets mutate it! First there is the
          //chance a neuron may be added
          if (baby.NumNeurons() < CParams::iMaxPermittedNeurons)
          {      
            baby.AddNeuron(CParams::dChanceAddNode,
                           *m_pInnovation,
                           CParams::iNumTrysToFindOldLink);
          }

          //now there's the chance a link may be added
          baby.AddLink(CParams::dChanceAddLink,
                       CParams::dChanceAddRecurrentLink,
                       *m_pInnovation,
                       CParams::iNumTrysToFindLoopedLink,
                       CParams::iNumAddLinkAttempts);

          //mutate the weights
          baby.MutateWeights(CParams::dMutationRate,
                             CParams::dProbabilityWeightReplaced,
                             CParams::dMaxWeightPerturbation);

          baby.MutateActivationResponse(CParams::dActivationMutationRate,
                                        CParams::dMaxActivationPerturbation);
        }

        //sort the babies genes by their innovation numbers
        baby.SortGenes();

        //add to new pop
        NewPop.push_back(baby);

        ++NumSpawnedSoFar;

        if (NumSpawnedSoFar == CParams::iNumSweepers)
        {        
          NumToSpawn = 0;
        }

      }//end while
       
    }//end if
     
  }//next species


  //if there is an underflow due to the rounding error and the amount
  //of offspring falls short of the population size additional children
  //need to be created and added to the new population. This is achieved
  //simply, by using tournament selection over the entire population.
  if (NumSpawnedSoFar < CParams::iNumSweepers)
  {

    //calculate amount of additional children required
    int Rqd = CParams::iNumSweepers - NumSpawnedSoFar;

    //grab them
    while (Rqd--)
    {
      NewPop.push_back(TournamentSelection(m_iPopSize/5));
    }
  }

  //replace the current population with the new one
  m_vecGenomes = NewPop;

  //create the new phenotypes
  vector<CNeuralNet*> new_phenotypes;

  for (gen=0; gen<m_vecGenomes.size(); ++gen)
  {
    //calculate max network depth
    int depth = CalculateNetDepth(m_vecGenomes[gen]);
    
    CNeuralNet* phenotype = m_vecGenomes[gen].CreatePhenotype(depth);

    new_phenotypes.push_back(phenotype);
  }

  //increase generation counter
  ++m_iGeneration;

  return new_phenotypes;
}