这也是人工智能实验的一个题目
- 这是一个很简陋的遗传算法版本,只有交叉(交配)
- 因为种群个体只有2个
- 迭代次数到达后即停止
//@edit 2018/11/29
#include<iostream>
#include<fstream>
using namespace std;
const int CITY_NUM = 7; //走过城市数量 0 x x x x x 0
const int RAND_GENE = 2;
float city_dis[CITY_NUM-1][CITY_NUM-1];
class individual
{
public:
int gene[CITY_NUM]; //个体基因,从城市0开始出发,到0结束
float fitness; //适应度,20.0/distance
int distance; //计算当前基因(路线)下的总距离
individual(int gene0,int gene1,int gene2,int gene3,int gene4)
{//初始化基因
gene[0]=gene0;
gene[1]=gene1;
gene[2]=gene2;
gene[3]=gene3;
gene[4]=gene4;
//基因传递后执行update函数(计算fitness和distance)
update_info();
}
individual(int gene0,int gene1,int gene2,int gene3,int gene4,int gene5,int gene6)
{//初始化基因 //7
gene[0]=gene0;
gene[1]=gene1;
gene[2]=gene2;
gene[3]=gene3;
gene[4]=gene4;
gene[5]=gene5;
gene[6]=gene6;
//基因传递后执行update函数(计算fitness和distance)
update_info();
}
void set_new_gene(int *new_gene)
{//mid part gene
for(int i=1;i<CITY_NUM-1;++i)
{
this->gene[i] = new_gene[i-1];//gene和传递进来到new_gene开始计数值不同
}
update_info();//更新个体fitness和distance
}
void update_info()
{//更新fitness和distance的函数
int new_dis = 0;
for(int i=0;i<CITY_NUM-1;++i)
{
new_dis += city_dis[this->gene[i]][this->gene[i+1]];
}
this->distance = new_dis;
this->fitness = 20.0/this->distance;
}
};
class tsp
{
public:
int generation_counts; //迭代次数,控制循环结束时间
int best_route[CITY_NUM]; //存储目前最好的个体(路线)
int best_distance; //最好个体的路线距离
float best_fitness; //其适应度
individual *father1; //初始个体1(路线1
individual *father2; //初始个体2(路线2
tsp()
{
generation_counts = 100; //迭代次数500次
best_distance = 0;
best_fitness = 0;
load_city_distance(); //从文件加载城市距离
//father1 = new individual(0,2,1,3,0); //初始化个体1
father1 = new individual(0,1,2,3,4,5,0);
//try rand father sequence //取消下面备注则会生成随机的基因给初始个体
// int rand1[3];
// get_random_nums(rand1,3);
// father1->set_new_gene(rand1);
//father2 = new individual(0,1,3,2,0); //初始化个体2
father2 = new individual(0,2,3,1,5,4,0);
// int rand2[3];
// get_random_nums(rand2,3);
// father2->set_new_gene(rand2);
}
~tsp()
{//析构函数
delete father1;
delete father2;
}
void start_generate()
{//迭代总函数
srand(time(NULL)); //取随机数用
while(--generation_counts >= 0) //
{
cout<<"迭代:"<<generation_counts<<endl;
get_best_fornow(); //获取当前种群最好个体
switch_part_genes(); //交换两个体的随机2个基因,开始和结束的0基因不参加交换
}
}
void get_best_fornow()
{//判断当前种群是否比已有的best个体更优,有则替换
individual *now_the_best;
if(father1->fitness > father2->fitness)
{//找到两个个体最优,并用指针指向它
now_the_best = father1;
}
else
{
now_the_best = father2;
}
if(now_the_best->fitness > this->best_fitness)
{//better one will replace the original best individual
for(int i=0;i<CITY_NUM;++i)
{
this->best_route[i] = now_the_best->gene[i];//替换基因
}
this->best_distance = now_the_best->distance; //替换distance
this->best_fitness = now_the_best->fitness; //替换fitness
}
}
void switch_part_genes()
{//switch 2 random genes in individual
int gene_place1[2];
int gene_place2[2];
get_random_nums(gene_place1,2);//生成1-citynum-2范围中2个不同随机数给place1
get_random_nums(gene_place2,2);//生成1-citynum-2中2个不同随机数给place2
//start to switch
swap_gene(gene_place1,gene_place2);//交换基因
father1->update_info();//更新个体信息
father2->update_info();
//for test
cout<<"\tf1 gene:";
for(int i=0;i<CITY_NUM;++i)
cout<<father1->gene[i];
cout<<" fit:"<<father1->fitness<<endl;
cout<<"\tf2 gene:";
for(int i=0;i<CITY_NUM;++i)
cout<<father2->gene[i];
cout<<" fit:"<<father2->fitness<<endl;
}
void swap_gene(int loc1[2],int loc2[2])
{ //loc1 is for father1;loc 2 for father 2
//用loc1中的2个father1基因位置来交换loc2中2个father2基因的位置
// cout<<loc1[0]<<" "<<loc1[1]<<endl;
// cout<<loc2[0]<<" "<<loc2[1]<<endl;
for(int i=0;i<2;++i)
{ //father1[i] <-> father2[i]
int temp_father1_gene = father1->gene[loc1[i]];
father1->gene[loc1[i]] = father2->gene[loc2[i]];
father2->gene[loc2[i]] = temp_father1_gene;
}
clear_conflict(father1);//交换后可能出现冲突 比如01220这种序列,需要处理冲突
clear_conflict(father2);
}
void clear_conflict(individual *ptr)
{
bool flag=false;
for(int i=1;i<CITY_NUM;++i)
{
if(i==CITY_NUM-1)
{
if(flag == true)
{
i=0;
flag = false;
continue;
}
else
{
continue;
}
}
int conf_loc = has_conflict(ptr->gene,i,ptr->gene[i]);
if(conf_loc == -1)
continue;
//has conflict
flag = true;
++ptr->gene[i];
if(ptr->gene[i] == 6)
ptr->gene[i] = 1;
--i;
}
return;
}
int has_conflict(int gene[CITY_NUM],int place,int target)
{ //可能冲突位置只有123,0和4固定为城市0,只要1和2、1和3、2和3都不冲突,即基因不冲突
//不同返回值用于快速定位冲突位置
for(int i=place+1;i<CITY_NUM;++i)
{
if(gene[i] == target)
return i;
}
return -1;
}
bool get_random_nums(int *nums,int size)
{//给nums数组生成size个不同随机数
if(size <= 0)
{
return false;
}
if(size == 1)
{
nums[0] = rand()%3+1;//range 1-3
return true;
}
//size >= 2;
int range = CITY_NUM - 2;
for(int i=0;i<size;++i)
{//i is the target place
nums[i] = rand()%range+1;
for(int j=0;j<i;++j)
{//j seeking the same number
if(nums[i] == nums[j])
{
nums[i] = rand()%range+1;
j=-1;
}
}
}
return true;
}
void print_best_route()
{
cout<<"\nBEST ROUTE:";
for(int i=0;i<CITY_NUM;++i)
{
cout<<best_route[i]<<" ";
}
cout<<endl;
cout<<"DISTANCE:"<<this->best_distance<<endl;
cout<<"FITNESS:"<<this->best_fitness<<endl;
}
void load_city_distance()
{//从文件读取城市距离信息
char in_data[50];
ifstream in_stream;
in_stream.open("ds.txt",ios::in);
if(!in_stream.is_open())
return;
int j=0;
int k=0;
while(!in_stream.eof())
{
in_stream.getline(in_data,50);
for(int i=0;i<50;++i)
{
if(in_data[i]>= '0' && in_data[i] <= '9')
{
city_dis[j][k++] = in_data[i]-'0';
if(k==CITY_NUM-1)
{
k=0;
++j;
break;
}
}
}
}
in_stream.close();
}
};
int main()
{
tsp tsp_demo;
tsp_demo.start_generate();
tsp_demo.print_best_route();
return 0;
}
附测试截图
ds.txt 文件内容
0 1 3 4 2 4
1 0 2 5 1 2
3 2 0 3 4 3
4 5 3 0 3 1
2 1 4 3 0 5
4 2 3 1 5 0