初始一个群落,要求群落最终从入口移动到出口,例子来源于《游戏编程中的人工智能技术》一书,并会有所改变。
- 变异会改变基因样式和长度
- 杂交采用轮盘法选取父母
#include <iostream>
#include <opencv2/opencv.hpp>
#include <algorithm>
#include <ctime>
#include <algorithm>
using namespace std;
using namespace cv;
struct Individual //个体
{
vector<int> gene;
int gene_num;
int dFitness;
int pos_x;
int pos_y;
Individual():gene_num(0),dFitness(0){pos_x = 2;pos_y =0;}
Individual(const int num_bits):gene_num(num_bits),dFitness(0)
{
//创造随机二进制位串
// srand((unsigned)time(0));
pos_x = 2;pos_y =0;
for (int i=0; i<num_bits; ++i)
{
int a = rand()%4;
gene.push_back(a);
}
}
};
class CBobMap
{
private:
static const int MAP_H = 10;
static const int MAP_W = 15;
static const int StartX = 2;
static const int StartY = 0;
static const int EndX = 7;
static const int EndY = 14;
public:
static const int map[MAP_H][MAP_W];
// int gene[MAP_H][MAP_W];
CBobMap(){
}
int Adapt_Score(Individual& ind)
{
vector<int> vecPath = ind.gene;
int sta_x = StartX;
int sta_y = StartY;
int ret =0;
for(auto it =vecPath.begin();it!=vecPath.end();it++)
{
switch(*it)
{
case 3:
{
if(sta_y-1>=0)
{
if(map[sta_x][sta_y-1]!=1)
{ sta_y --;
}
}
}
break;
case 2:
{
if(sta_y+1<15)
{
if(map[sta_x][sta_y+1]!=1)
{ sta_y ++;}
}
}
break;
case 1:
{
if(sta_x+1<10)
{
if(map[sta_x+1][sta_y]!=1)
{
sta_x ++;
}
}
}
break;
case 0:
{
if(sta_x-1>=0)
{
if(map[sta_x-1][sta_y]!=1)
{
sta_x --;
}
}
}
break;
default:
break;
}
ret += abs(EndX-sta_x) + abs(EndY - sta_y);
}
ind.pos_x = sta_x;
ind.pos_y = sta_y;
ind.dFitness = ret;
return ind.dFitness;
}
};
const int CBobMap::map[MAP_H][MAP_W] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,0,1,0,0,0,0,0,1,1,1,0,0,0,1,
5,0,0,0,0,0,0,0,1,1,1,0,0,0,1,
1,0,0,0,1,1,1,0,0,1,0,0,0,0,1,
1,0,0,0,1,1,1,0,0,0,0,0,1,0,1,
1,1,0,0,1,1,1,0,0,0,0,0,1,0,1,
1,0,0,0,0,1,0,0,0,0,1,1,1,0,1,
1,0,1,1,0,0,0,1,0,0,0,0,0,0,8,
1,0,1,1,0,0,0,1,0,0,0,0,0,0,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 };
class Community //群落
{
private:
vector<Individual> community;
vector<int> AdaptScores;
const static int community_size;
int AdaptScore_sum;
const static double Mutate_Ratio; //突变率
const static double Crossover_Ratio; //杂交率
CBobMap Map;
public:
void Mutate()
{
random_shuffle(community.begin(),community.end());
for(int i=0;i<community_size*Mutate_Ratio*6;i++)
{
int postion = rand()%(community[i].gene.size());
community[i].gene[postion] = rand()&0x03;
community[i].gene.push_back(rand()&0x03);
community[i].gene_num = community[i].gene.size();
}
}
void Crossover()
{
vector<Individual> com_;
com_.resize(community_size);
for(int i=0;i<community_size;i+=2)
{
Individual father,mother;
RouletteWheelSelection(father,mother);
unsigned int position = rand()%father.gene_num;
vector<int> gene_temp = father.gene;
father.gene.resize(mother.gene_num);
for(unsigned int i=0;i<position && i<father.gene.size();i++)
{
father.gene[i] = gene_temp[i];
}
for(unsigned int i=position;i<father.gene.size();i++)
{
father.gene[i] = mother.gene[i];
}
mother.gene.resize(gene_temp.size());
for(unsigned int i=position;i<mother.gene.size();i++)
{
mother.gene[i] = gene_temp[i];
}
com_[i]= father;
com_[i+1]=mother;
}
community = com_;
}
void RouletteWheelSelection(Individual& Father,Individual& Mother)
{
int father = rand()%AdaptScore_sum;
auto it = community.begin();
int sum=0;
for(;it!=community.end();it++)
{
sum+=(it->dFitness);
if(sum>father)
{
Father = *it;
break;
}
}
auto it_father= it;
int mother = rand()%(AdaptScore_sum- it_father->dFitness);
it = community.begin();
sum=0;
for(;it!=community.end();it++)
{
sum+=(it->dFitness);
if(sum>mother && it!=it_father)
{
Mother = *it;
break;
}
}
}
Community():AdaptScore_sum(0)
{
community.resize(community_size);
AdaptScores.resize(community_size);
for(int i=0;i<community_size;i++)
{
AdaptScores[i]=0;
Individual a(10);
community[i]=a;
}
}
void run()
{
for(int generation=0;generation<2000;generation++)
{
int Score_max = 0;
for(auto it= community.begin();it!=community.end();it++)
{
int score = Map.Adapt_Score(*it);
if(score>Score_max)
Score_max = score;
}
AdaptScore_sum=0;
for(auto it= community.begin();it!=community.end();it++)
{
it->dFitness = Score_max+5 - it->dFitness;
AdaptScore_sum += it->dFitness;
}
bool cap[10][15]={0};
for(auto it= community.begin();it!=community.end();it++)
{
cap[it->pos_x][it->pos_y] = true;
}
Mat img(10,15,CV_8UC1);
for(int i=0;i<10;i++)
for(int j=0;j<15;j++)
{
if(CBobMap::map[i][j]==1)
{
uchar *data = img.ptr<uchar>(i);
data[j] = 0;
}
else if(cap[i][j])
{
uchar *data = img.ptr<uchar>(i);
data[j] = 155;
}
else
{
uchar *data = img.ptr<uchar>(i);
data[j] = 255;
}
}
imshow("HJ",img);
waitKey(10);
Crossover();
Mutate();
}
}
};
const double Community::Mutate_Ratio = 0.001; //突变率
const double Community::Crossover_Ratio = 0.7; //杂交率
const int Community::community_size=1000;
int main()
{
Community Com;
Com.run();
return 1;
}