⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gatsp.cpp

📁 游戏开发人工智能技术-AI.Techniques.for.Game.Programming
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	if ( (RandFloat() > m_dCrossoverRate) || (mum == dad)) 
	{
    //make sure baby1 and baby2 are assigned some cities first!
    baby1 = mum;
    baby2 = dad;
    
		return;
	}

  //initialize the babies with minus values so we can tell which positions
  //have been filled later in the algorithm
  baby1.assign(mum.size(), -1);
  baby2.assign(mum.size(), -1);

  int l = baby2.size();

  //holds the positions of the chosen cities
  vector<int> positions;

  //first city position
  int Pos = RandInt(0, mum.size()-2);

  //keep adding random cities until we can add no more
  //record the positions as we go
  while (Pos < mum.size())
  {
    positions.push_back(Pos);

    //next city
    Pos += RandInt(1, mum.size()-Pos);
  }
  
  //now we have chosen some cities it's time to copy the selected cities
  //over into the offspring in the same position.
  for (int pos=0; pos<positions.size(); ++pos)
  {
    //baby1 receives from mum
    baby1[positions[pos]] = mum[positions[pos]];

    //baby2 receives from dad
    baby2[positions[pos]] = dad[positions[pos]];
  }

  //fill in the blanks. First create two position markers so we know
  //whereabouts we are in baby1 and baby2
  int c1 = 0, c2 = 0;

  for (pos=0; pos<mum.size(); ++pos)
  {   
    //advance position marker until we reach a free position
    //in baby2
    while( (baby2[c2] > -1) && (c2 < mum.size()))
    {
      ++c2;
    }
    
    //baby2 gets the next city from mum which is not already
    //present
    if ( (!TestNumber(baby2, mum[pos])) )
    {
      baby2[c2] = mum[pos]; 
    }

    //now do the same for baby1
    while((baby1[c1] > -1) && (c1 < mum.size()))
    {      
      ++c1;
    }
    
    //baby1 gets the next city from dad which is not already
    //present
    if ( (!TestNumber(baby1, dad[pos])) )
    {
      baby1[c1] = dad[pos];
    }     
  }
}
//--------------------- Crossover ----------------------------------------
//
//  simple switch statement to perform crossover based on the selected
//  CrossoverType, type
//------------------------------------------------------------------------
void CgaTSP::Crossover(const vector<int>	&mum, 
							         const vector<int>	&dad, 
							         vector<int>        &baby1, 
							         vector<int>        &baby2,
                       CrossoverType      type)
{
  //perform crossover based on type
  switch(type)
  {
  case OBX:

    CrossoverOBX(mum, dad, baby1, baby2);

    break;

  case PMX:

    CrossoverPMX(mum, dad, baby1, baby2);

    break;

  case PBX:

    CrossoverPBX(mum, dad, baby1, baby2);

    break;


  default: break;

  }//end switch
}

//-----------------------CreateStartingPopulation()------------------------
//
//	clears any existing population, fills a vector with a random population
//	of genomes and resets appropriate member variables
//-------------------------------------------------------------------------
void CgaTSP::CreateStartingPopulation()
{
	//make sure the vector of genomes is empty before we
	//start
	m_vecPopulation.clear();
	
	//create a new population of random genomes
	for (int i=0; i<m_iPopSize; ++i)
	{
		m_vecPopulation.push_back(SGenome(m_iChromoLength));
	}

	//make sure variables are initialised correctly
	m_iGeneration	        = 0;
	m_dShortestRoute      = 9999999;
	m_dBestFitness	      = 0;
	m_dWorstFitness       = 9999999;
	m_dAverageFitness     = 0;
	m_iFittestGenome      = 0;
	m_bStarted			      = false;
  m_dBoltzmannTemp      = NUM_CITIES * 2;

}
//-----------------------------------Run-----------------------------------
//
//	This is the function that initializes a new population and sets the
//  ga running 
//------------------------------------------------------------------------
void CgaTSP::Run(HWND hwnd)
{
	//The first thing we have to do is create a random population
	//of genomes
	CreateStartingPopulation();

	m_bStarted = true;

}
//-------------------------Reset()------------------------------
//
//	resets all the relevant variables ready for a new generation
//--------------------------------------------------------------
void CgaTSP::Reset()
{
	//just make the shortest route some excessively large distance
	m_dShortestRoute	= 999999999;
	m_dLongestRoute		= 0;
	m_dTotalFitness		= 0;
	m_dBestFitness		= 0;
	m_dWorstFitness		= 9999999;
	m_dAverageFitness	= 0;
	m_bSorted			    = false;
  m_dSigma          = 1;
}

//------------------------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;
}

//-------------------------------Render-------------------------------
//
//	This function does all the drawing and textual output. Called from
// the winproc when it receives a WM_PAINT msg
//--------------------------------------------------------------------
void CgaTSP::Render(HDC surface, int cx, int cy)const
{

		//draw all the cities
	for (int city_num = 0; city_num < m_pMap->m_vecCityCoOrds.size(); ++city_num)
	{
		int x = (int)m_pMap->m_vecCityCoOrds[city_num].x;
		int y = (int)m_pMap->m_vecCityCoOrds[city_num].y;
		
		Ellipse(surface, x-CITY_SIZE, y+CITY_SIZE, x+CITY_SIZE, y-CITY_SIZE);
	}
	
	//draw the fittest route so far
	vector<int> route = m_vecPopulation[m_iFittestGenome].vecCities;
	
	//only display the routes if we are in a run
	if (m_iGeneration != 0)
	{ 
		MoveToEx(surface, (int)m_pMap->m_vecCityCoOrds[route[0]].x, (int)m_pMap->m_vecCityCoOrds[route[0]].y, NULL);
		
		for (int i=1; i<route.size(); ++i)
		{
			int CityX = (int)m_pMap->m_vecCityCoOrds[route[i]].x;
			int CityY = (int)m_pMap->m_vecCityCoOrds[route[i]].y;
			
			LineTo(surface, CityX, CityY);
			
			//draw the numbers representing the order the cities are visited.
			//No point drawing them after about a 100 cities as the display
			//just becomes confused
			if (NUM_CITIES < 100)
			{
				string CityNumber = itos(i);
			
				TextOut(surface, CityX, CityY, CityNumber.c_str(), CityNumber.size());
			}
		}

		//now draw the line from the last city visited back to the starting point
		LineTo(surface, (int)m_pMap->m_vecCityCoOrds[route[0]].x, (int)m_pMap->m_vecCityCoOrds[route[0]].y);
	}	
	
	//print stats
	string sGen = itos(m_iGeneration);
	sGen = "Generation: " + sGen;
	TextOut(surface, 5, cy - 20, sGen.c_str(), sGen.size());


	if (!m_bStarted)
	{
		string Start = "Press Return to start a new run";

		TextOut(surface, cx/2 - (Start.size() * 3), cy - 20, Start.c_str(), Start.size());

    if (m_dSigma == 0)
    {
      string s = "Premature Convergence!";

      TextOut(surface, cx-40 - (Start.size() * 3), cy-20, s.c_str(), s.size());
    }
	}

	else

	{
		string Start = "Space to stop";
		
		TextOut(surface, cx/2 - (Start.size() * 3), cy - 20, Start.c_str(), Start.size());
	}	

 

  //render the current Boltzmann temperature if applicable
  if (m_ScaleType == BOLTZMANN)
  {
    string s = "Boltzmann Temp: " + ftos(m_dBoltzmannTemp);
    TextOut(surface, 400, 5, s.c_str(), s.size());
  }
    
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -