以下是遗传算法(GA)解决旅行商问题(TSP)源码:
#include <iostream>
#include <vector>
#include <ctime>
#include <algorithm>
#include <cmath>
using namespace std;
#define INF 1000
typedef struct individual{
vector<int> chrom;
double fit;
double percentage;
int pathL;
};
bool compare(individual a, individual b){ return a.percentage > b.percentage; }
class SGA
{
public:
SGA();
SGA(int psize, int gen, int maxgen, double c, double m) :popsize(psize), Genlen(gen), maxgener(maxgen), pc(c), pm(m){}
~SGA();
void Initial(int** a);
void Select(int** a);
void Variation();
void mutation();
void evolution(int** a);
void print();
void updateData(int** a);
private:
vector<individual > matingpool;
int popsize;//种群大小
int Genlen;//基因长度,也即城市个数
int maxgener;//迭代代数
double pc;
double pm;
bool IsNotExit(individual vc, int start, int end, int value);
vector<int> BuildRandomSequence(int len);
};
SGA::SGA()
{
}
bool SGA::IsNotExit(individual vc, int start, int len, int value)
{
for (size_t t = start; t != start + len; t++) if (vc.chrom[t] == value) return false;
return true;
}
//随机产生序列,也即随机产生个体
vector<int> SGA::BuildRandomSequence(int length)
{
vector<int> vc;
int i;
for (i = 0; i < length; i++) vc.push_back(i);
int x = 0, tmp = 0;
for (i = length - 1; i > 0; i--) {
//x = random.Next(0, i + 1);
x = rand() % (i + 1);
tmp = vc[i];
vc[i] = vc[x];
vc[x] = tmp;
}
return vc;
}
//更新每个个体的fitness
void SGA::updateData(int** a)
{
double ftotal = 0;
int path = 0;
for (size_t t = 0; t < matingpool.size(); t++)
{
for (size_t x = 1; x < Genlen; x++)
path += *((int*)a + Genlen*matingpool[t].chrom[x - 1] + matingpool[t].chrom[x]);
path += *((int*)a + Genlen*matingpool[t].chrom[0] + matingpool[t].chrom[Genlen-1]);
matingpool[t].pathL = path;
matingpool[t].fit = 1.0 / path;
path = 0;
ftotal += matingpool[t].fit;
}
for (size_t tt = 0; tt < matingpool.size(); tt++)
{
matingpool[tt].percentage = matingpool[tt].fit / ftotal;
}
}
//初始化种群
void SGA::Initial(int** a)
{
int i, j=1;
individual ida;
int path = 0;
for (j = 0; j < popsize; j++)
{
ida.chrom = BuildRandomSequence(Genlen);
matingpool.push_back(ida);
}
updateData(a);
}
void SGA::Select(int** a)
{
//选择个体加入 mating pool,可能重复
vector<individual> vcida;
updateData(a);
for (size_t i = 0; i < matingpool.size(); i++)
{
vcida.push_back(matingpool[i]);
}
matingpool.clear();
double rate;
double ff = 0.0;
srand((unsigned)time(NULL));
while (1)
{
rate = rand()*1.0 / RAND_MAX;
for (int i = 0; i < popsize; i++)
{
if (rate>ff && rate <= vcida[i].percentage + ff)
{
matingpool.push_back(vcida[i]);
break;
}
ff += vcida[i].percentage;
}
ff = 0.0;
if (matingpool.size() == popsize) break;
}
updateData(a);
}
void SGA::Variation()
{
//Parent交叉产生Offspring,pc为交叉率,即参加交叉运算的染色体数占全部染色体总数的百分比
int pcd = popsize / 2 * pc;
vector<individual> crw;
sort(matingpool.begin(), matingpool.end(), compare);
int cnt = 0;
for (size_t i = popsize-1; cnt!=2*pcd; i--,cnt++)
{
crw.push_back(matingpool[i]);
}
int i,j;
srand((unsigned)time(NULL));
int start = rand() % (Genlen - 3);
int length = rand() % (Genlen - start);
individual a, b,o1,o2;
vector<int> ttp;
for (i = 0; i != 2 * pcd; i+=2)
{
a = crw[i];
b = crw[i+1];
o1 = a;
o2 = b;
ttp.clear();
for (j = 0; j != Genlen; j++)
{
if (IsNotExit(o1, start, length, b.chrom[j]))
ttp.push_back(b.chrom[j]);
}
for (j = 0; j < start; j++)
{
o1.chrom[j] = ttp[j];
}
for (j = start+length; j < Genlen; j++)
{
o1.chrom[j] = ttp[j - start - length ];
}
ttp.clear();
for (j = 0; j != Genlen; j++)
{
if (IsNotExit(o2, start, length, a.chrom[j]))
ttp.push_back(a.chrom[j]);
}
for (j = 0; j < start; j++)
{
o2.chrom[j] = ttp[j];
}
for (j = start + length ; j < Genlen; j++)
{
o2.chrom[j] = ttp[j - start - length ];
}
matingpool.push_back(o1);
matingpool.push_back(o2);
}
crw.clear();
ttp.clear();
}
//突变操作
void SGA::mutation()
{
int pcd = popsize * pm;
int i, pos1,pos2, tp,tt;
srand((unsigned)time(NULL));
for (i = 0; i < pcd; i++)
{
tp = rand() % matingpool.size();
pos1 = rand() % Genlen;
pos2 = rand() % Genlen;
tt = matingpool[tp].chrom[pos1];
matingpool[tp].chrom[pos1]= matingpool[tp].chrom[pos2];
matingpool[tp].chrom[pos2] = tt;
}
}
//进化操作
void SGA::evolution(int** a)
{
int gen = 0;
while (gen != maxgener)
{
Variation();
mutation();
Select(a);
gen++;
}
}
void SGA::print()
{
int i,k, P=10000;
for (i = 0; i < popsize; i++)
{
if (matingpool[i].pathL < P)
{
P = matingpool[i].pathL;
k = i;
}
}
cout << "最短距离: " << matingpool[k].pathL << endl;
cout << "最短路径: " ;
for (i = 0; i < Genlen; i++) cout << matingpool[k].chrom[i] << " ";
cout << matingpool[k].chrom[0];
cout << endl;
}
SGA::~SGA()
{
}