1、//遗传算法解决简单TSP问题,(VC6.0) //一、定义头文件(defines.h) #ifndef DEFINES_H #define DEFINES_H ///////////////////////////////// DEFINES /////////////////////////////////////// //窗口定义大小 #define WINDOW_WIDTH 500 #define WINDOW_HEIGHT 500 //城市数量及城市在窗口显示的大小 #define NUM_CITIES 20 #define CITY_SIZE
2、 5 //变异概率,交叉概率及种群数量 #define MUTATION_RATE 0.2 #define CROSSOVER_RATE 0.75 #define POP_SIZE 40 //倍数 #define NUM_BEST_TO_ADD 2 //最小容许误差 #define EPSILON 0.000001 #endif //二、一些用得到的小函数(utils.h) // utils.h: interface for the Cutils class. //头文件名 ////////////////////////////
3、//////////////////////////////////////////
#ifndef UTILS_H
#define UTILS_H
#include
4、 return rand()%(y-x+1)+x; } //--------------随机产生0到1之间的小数---------- inline float RandFloat() { return rand()/(RAND_MAX + 1.0); } //-----------------随机产生0和1------------- inline bool RandBool() { if (RandInt(0,1)) return true; else return false; } //-----定义一些方便的小功能包括:整形转
5、字符型,浮点型转字符型--- string itos(int arg); //converts an float to a std::string string ftos (float arg); //限制大小 void Clamp(double &arg, double min, double max); void Clamp(int &arg, int min, int max); #endif //三、地图头文件(CmapTSP) #ifndef CMAPTSP_H #define CMAPTSP_H//如果没有定义那么就定义 ////////////
6、//////////////////////////////////////
//类名:CmapTSP.h
//
//描述:封装地图数据、城市坐标以及适应度计算。
/////////////////////////////////////////////////
#include
7、struct CoOrd//没有括号 { float x, y; CoOrd(){} CoOrd(float a,float b):x(a),y(b){} }; //------CmapTSP类,封装地图数据,城市坐标,以及适应度计算---- class CmapTSP { private: //城市数目 int m_NumCities; //地图长度和宽度 int m_MapWidth; int m_MapHeight; //可能最好路径 double m_dBestPossibleRoute; //把所有城市组成一
8、个环形
void CreateCitiesCircular();
//用勾股定理计算两个城市A和B之间的距离
double CalculateA_to_B(const CoOrd &city1, const CoOrd &city2);
//该函数计算出排列成环形后的最佳路径,答案是显而易见的(环形多边形周长)
void CalculateBestPossibleRoute();
public:
//城市坐标
vector
9、径
CmapTSP(int w, int h, int nc):m_MapWidth(w),
m_MapHeight(h),m_NumCities(nc)
{
CreateCitiesCircular();
CalculateBestPossibleRoute();
}
//改变窗口坐标时
void Resize(const int new_width, const int new_Height);
//给一个有效的周游路径,返回该路径长度
double GetTourLength(const vector
10、
double BestPossibleRoute()const{return m_dBestPossibleRoute;}
};
#endif
//四、遗传算法头文件(CgaTSP)
#ifndef CGATSP_H
#define CGATSP_H
#include
11、e "utils.h"
using namespace std;
//----------基因组结构体(包含旅行路径和其适应度函数)----------
struct SGenome
{
//周游城市路径,(基因组)
vector
12、游路径
vector
13、变异概率 double m_dMutationRate; double m_dCrossoverRate; //整个种群的总适应度分数 double m_dTotalFitness; //在此之前找到的最短路径 double m_dShortestRoute; //在此之前找到的最长周游路径 double m_dLongestRoute; //种群中基因组的数目 int m_iPopSize; //染色体长度 int m_iChromoLength; //新一代中适应度分数最高的成员 int m_iFittestG
14、enome;
//表明已经到了那一代
int m_iGeneration;
//帮助了解长须当前是否进入绘图阶段
bool m_bStarted;
//交换变异(Exchange Mutation)
void MutateEM(vector
15、
16、 NumCities, int map_width, int map_height):m_dMutationRate(mut_rat), m_dCrossoverRate(cross_rat), m_iPopSize(pop_size), m_iFittestGenome(0), m_iGeneration(0), m_dShortestRoute(999999999), m_dLongestRoute(0),
17、 m_iChromoLength(NumCities), m_bStarted(false) { //设置地图 m_pMap = new CmapTSP(map_width, map_height, NumCities); CreateStartingPopulation(); } //析构函数 ~CgaTSP(){delete m_pMap;} void Run(HWND hwnd); void Epoch(); void Render(HDC surface, int cx, int cy);
18、 void Resize(int cxClient, int cyClient) { m_pMap->Resize(cxClient, cyClient); } //供使用的方法 void Stop(){m_bStarted = false;} bool Started(){return m_bStarted;} }; #endif //五、一个其实没有用的头文件(StdAfx.h) #if !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000_
19、INCLUDED_)
#define AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include
20、源文件---------------///////////////////////////////-
//一、utils.cpp
// utils.cpp: implementation of the Cutils class.
//
//////////////////////////////////////////////////////////////////////
#include "utils.h"
#include
21、/////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// //--------itos讲一个整数变换成字符串----------- string itos(int arg) { ostringstream buffer; //把整形发送到buffer buffer << arg; //获取字符串 return buffer.str(); } //-----
22、把浮点型转换为字符串型----------
string ftos(float arg)
{
ostringstream buffer;
buffer << arg;
return buffer.str();
}
//限制范围
void Clamp(double &arg, double min, double max)
{
if (arg
23、 max) { if (arg < min) { arg = min; } if (arg > max) { arg = max; } } //二、mapTSP.cpp // mapTSP.cpp: implementation of the CmapTSP class. // ////////////////////////////////////////////////////////////////////// #include "mapTSP.h" ///////////////////////////////
24、///////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//--------把城市排列成圆圈--------------(已改正)
void CmapTSP::CreateCitiesCircular()
{
const int margin = 50;//边缘
double radius;//圆半径
if (m_MapHeight 25、th)
{
radius = (m_MapHeight / 2) - margin;
}
else
{
radius = (m_MapWidth / 2) - margin;
}
CoOrd origin(m_MapWidth/2, m_MapHeight/2);//原点
double SegmentSize = 2 * pi / m_NumCities;//角度
double angle = 0;//起始角度
vector 26、sCity;//声明对象
ThisCity.x = radius * sin(angle) + origin.x;//犯错误处少乘radius *
ThisCity.y = radius * cos(angle) + origin.y;
m_vecCityCoOrds.push_back(ThisCity);
angle += SegmentSize;
}
}
//------------计算两个城市之间的路径----------
double CmapTSP::CalculateA_to_B(const CoOrd &city 27、1, const CoOrd &city2)
{
double xDist = city1.x - city2.x;
double yDist = city1.y - city2.y;
return sqrt(xDist*xDist + yDist*yDist);
}
//-------------计算最佳路径------------
void CmapTSP::CalculateBestPossibleRoute()
{
m_dBestPossibleRoute = 0;
for (int city=0; city 28、size()-1; ++city)
{
m_dBestPossibleRoute += CalculateA_to_B(m_vecCityCoOrds[city], m_vecCityCoOrds[city+1]);
m_dBestPossibleRoute += EPSILON;//加入误差
}
m_dBestPossibleRoute += CalculateA_to_B(m_vecCityCoOrds[0], m_vecCityCoOrds[m_vecCityCoOrds.size()-1]);//少减个1,size()-1
}
//- 29、屏幕坐标变化时-----------------
void CmapTSP::Resize(const int new_width, const int new_height)
{
m_MapWidth = new_width;
m_MapHeight = new_height;
m_vecCityCoOrds.clear();
CreateCitiesCircular();
CalculateBestPossibleRoute();
}
//-------------得到一条路线的距离长度------------------- 30、
double CmapTSP::GetTourLength(const vector 31、rget this is a closed loop so we need to add in the distance
//from the last city visited back to the first
int last = route[route.size()-1];
int first = route[0];
TotalDistance += CalculateA_to_B(m_vecCityCoOrds[last], m_vecCityCoOrds[first]);
return TotalDistance;
}
// mapTSP 32、cpp: implementation of the CmapTSP class.
//
//////////////////////////////////////////////////////////////////////
//三、gaTSP.cpp
// gaTSP.cpp: implementation of the CgaTSP class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "gaT 33、SP.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
/////////----------------------------------------------
/////////------------结构体函数------------------------
///////// 34、
///////////////////////////////////////////////////////
//该函数检查给定的一个整数是否包含在给定的一个向量里边
bool SGenome::TestNumber(const vector 35、 }
return false;
}
//////////////////////////////////////////////////////////
//给定一个整数,该函数返回随机排列的路径
////////////////////////////////////////////////////////
vector 36、Number = RandInt(0, limit-1);
while (TestNumber(vecPerm, NextPossibleNumber))
{
NextPossibleNumber = RandInt(0,limit-1);
}
vecPerm.push_back(NextPossibleNumber);
}
return vecPerm;
}
////////-------------------------------------
////////---------类内函数------------------ 37、
////////-------------------------------------
/////该函数计算每个基因的适应度分数
void CgaTSP::CalculatePopulationsFitness()
{
for (int i=0; i 38、Length;
if (TourLength 39、vecPopulation[j].dFitness;
}
}
//-------------------轮盘选择,选择一个--------------------
SGenome& CgaTSP::RouletteWheelSelection()
{
double fSlice = RandFloat() * m_dTotalFitness;
double cfTotal = 0.0;
int SelectedGenome = 0;
for (int i=0; i 40、Population[i].dFitness;
if (cfTotal>fSlice)
{
SelectedGenome = i;
break;
}
}
return m_vecPopulation[SelectedGenome];
}
//--------随机选择区间,用来交叉和变异---------
void ChooseSection(int &beg, int &end, const int vec_size, const int min_span)
{
beg = RandInt(0, vec_size-1-min_spa 41、n);
end = beg;
while (end 42、
{
pos2 = RandInt(0, chromo.size()-1);
}
swap(chromo[pos1], chromo[pos2]);
}
//----------------交叉-------------------
void CgaTSP::CrossoverPMX(const vector 43、 dad;
if ((RandFloat()>m_dCrossoverRate)||(mum == dad))
{
return;
}
int beg = RandInt(0, mum.size()-2);
int end = beg;
while(end<=beg)
{
end = RandInt(0, mum.size()-1);
}
//遍历每个基因地址下标
vector 44、 int gene1 = mum[pos];
int gene2 = dad[pos];
if (gene1 != gene2)
{
posGene1 = find(baby1.begin(),baby2.end(),gene1);
posGene2 = find(baby1.begin(), baby1.end(), gene2);
swap(*posGene1, *posGene2);
//and in baby2
posGene1 = find(baby2.begin(), baby2.end(), gene1);
45、 posGene2 = find(baby2.begin(), baby2.end(), gene2);
swap(*posGene1, *posGene2);
}
}
}
//----------产生初始群体------------------
void CgaTSP::CreateStartingPopulation()
{
m_vecPopulation.clear();
for (int i=0; i 46、oLength));
}
m_iGeneration = 0;
m_dShortestRoute = 9999999;
m_iFittestGenome = 0;
m_bStarted = false;
}
//---------------运行-------
void CgaTSP::Run(HWND hwnd)
{
CreateStartingPopulation();
m_bStarted = true;
}
//---------重置所有变量为新的一代----------
void CgaTSP::Reset()
{
m_d 47、ShortestRoute = 999999999;
m_dLongestRoute = 0;
m_dTotalFitness = 0;
}
//-----------------组合在一起---------------
void CgaTSP::Epoch()
{
//为新的一代重置
Reset();
CalculatePopulationsFitness();
if ((m_dShortestRoute <= m_pMap->BestPossibleRoute()))
{
m_bStarted = false;
r 48、eturn;
}
//创建一个临时的向量作为新的种群
vector 49、WheelSelection();
SGenome baby1, baby2;
CrossoverPMX(mum.vecCities,
dad.vecCities,
baby1.vecCities,
baby2.vecCities);
MutateEM(baby1.vecCities);
MutateEM(baby2.vecCities);
vecNewPop.push_back(baby1);
vecNewPop.push_back(baby2);
}
m 50、vecPopulation = vecNewPop;
++m_iGeneration;
}
//--Rander函数把函数信息从文本和图像中输出winproc----
void CgaTSP::Render(HDC surface, int cx, int cy)
{
for (int city_num=0; city_num






