遗传算法
来源:互联网 发布:数据分析师 编辑:程序博客网 时间:2024/04/27 17:29
为了hollow游戏 各个关卡通关。需要一种算法找到block move路径。开始考虑A*算法,以及相关的深度优先搜索或者广度优先搜索,可是这种搜索算法需要do one move,back one move两种过程,hollow游戏中back one move需要记录n多信息。最后决定用遗传学算法,不需做back one move处理。以下内容来自 百度百科 ''遗传算法"
遗传算法是基于生物学的,理解或编程都不太难。下面是遗传算法的一般算法:
创建一个随机的初始状态
初始种群是从解中随机选择出来的,将这些解比喻为染色体或基因,该种群被称为第一代,这和符号人工智能系统的情况不一样,在那里问题的初始状态已经给定了。
评估适应度
对每一个解(染色体)指定一个适应度的值,根据问题求解的实际接近程度来指定(以便逼近求解问题的答案)。不要把这些“解”与问题的“答案”混为一谈,可以把它理解成为要得到答案,系统可能需要利用的那些特性。
繁殖(包括子代突变)
带有较高适应度值的那些染色体更可能产生后代(后代产生后也将发生突变)。后代是父母的产物,他们由来自父母的基因结合而成,这个过程被称为“杂交”。
下一代
如果新的一代包含一个解,能产生一个充分接近或等于期望答案的输出,那么问题就已经解决了。如果情况并非如此,新的一代将重复他们父母所进行的繁衍过程,一代一代演化下去,直到达到期望的解为止。
并行计算
非常容易将遗传算法用到并行计算和群集环境中。一种方法是直接把每个节点当成一个并行的种群看待。然后有机体根据不同的繁殖方法从一个节点迁移到另一个节点。另一种方法是“农场主/劳工”体系结构,指定一个节点为“农场主”节点,负责选择有机体和分派适应度的值,另外的节点作为“劳工”节点,负责重新组合、变异和适应度函数的评估。
一个遗传学编程实例
---------来个例子,大家好理解------------
基于遗传算法的人工生命模拟
#include<stdio.h>
#include<stdlib.h>
#include<graphics.h>
#include<math.h>
#include<time.h>
#include<string.h>
#include "graph.c"
/* 宏定义 */
#define TL1 20 /* 植物性食物限制时间 */
#define TL2 5 /* 动物性食物限制时间 */
#define NEWFOODS 3 /* 植物性食物每代生成数目 */
#define MUTATION 0.05 /* 变异概率 */
#define G_LENGTH 32 /* 个体染色体长度 */
#define MAX_POP 100 /* 个体总数的最大值 */
#define MAX_FOOD 100 /* 食物总数的最大值 */
#define MAX_WX 60 /* 虚拟环境的长度最大值 */
#define MAX_WY 32 /* 虚拟环境的宽度最大值 */
#define SX1 330 /* 虚拟环境图左上角点x坐标 */
#define SY1 40 /* 虚拟环境图左上角点y坐标 */
#define GX 360 /* 个体数进化图形窗口的左上角点X坐标 */
#define GY 257 /* 个体数进化图形窗口的左上角点Y坐标 */
#define GXR 250 /* 个体数进化图形窗口的长度 */
#define GYR 100 /* 个体数进化图形窗口的宽度 */
#define GSTEP 2 /* 个体数进化图形窗口的X方向步长 */
#define R_LIFE 0.05 /* 初期产生生物数的环境比率 */
#define R_FOOD 0.02 /* 初期产生食物数的环境比率 */
#define SL_MIN 10 /* 个体寿命最小值 */
/* 全局变量 */
unsigned char gene[MAX_POP][G_LENGTH]; /* 遗传基因 */
unsigned char iflg[MAX_POP]; /* 个体死活状态标志变量 */
unsigned char fflg[MAX_FOOD]; /* 食物有无状态标志变量 */
unsigned char world[MAX_WX][MAX_WY]; /* 虚拟环境的数据 */
unsigned char /* 各中行为模式数据 */
life1[5][5]={{0,0,1,0,0},{0,1,0,1,0},{1,0,0,0,1},{0,1,0,1,0},{0,0,1,0,0}};
unsigned char
life2[5][5]={{1,1,1,1,1},{1,0,0,0,1},{1,0,0,0,1},{1,0,0,0,1},{1,1,1,1,1}};
unsigned char
food1[5][5]={{0,0,0,1,0},{0,0,1,1,0},{0,1,0,1,0},{0,0,1,1,0},{0,0,0,1,0}};
unsigned char
food2[5][5]={{0,0,0,1,0},{0,0,1,1,0},{0,1,1,1,0},{0,0,1,1,0},{0,0,0,1,0}};
int pop_size; /* 个体总数 */
int iatr[MAX_POP][4]; /* 个体属性 */
/* iatr[][0] 个体当前位置x坐标 */
/* iatr[][1] 个体当前位置y坐标 */
/* iatr[][2] 内部能量 */
/* iatr[][3] 年龄属性 */
int food_size; /* 食物总数 */
int fatr[MAX_FOOD][4]; /* 食物属性 */
/* fatr[][0] 食物当前位置x坐标 */
/* fatr[][1] 食物当前位置y坐标 */
/* fatr[][2]=0 : 植物性 =1:动物性 */
/* fatr[][3] 新鲜程度 */
int wx,wy; /* 虚拟环境的长宽度 */
void uni_crossover(gene,g1,g2,g3,ratio1,g_length) /* 均匀交叉 */
unsigned char *gene; /* 遗传基因 */
int g1,g2,g3; /* g1 g2 父个体编号 g3 子个体编号 */
double ratio1; /* 父个体g1被选中的概率 */
int g_length; /* 个体遗传基因的位长 */
{
unsigned char *gene1; /* 父1遗传基因的指针 */
unsigned char *gene2; /* 父2遗传基因的指针 */
unsigned char *gene3; /* 子遗传基因的指针 */
double rnd,r1;
int i;
gene1=gene+g_length*g1;
gene2=gene+g_length*g2;
gene3=gene+g_length*g3;
r1=(int)(10000.0*ratio1);
for(i=0;i<g_length;i++)
{ rnd=random(10000);
if(rnd<=r1) *(gene3+i)=*(gene1+i);
else *(gene3+i)=*(gene2+i);
}
}
void g_disp_unit(x,y,n)
/* 绘制虚拟环境的一个单元 */
int x,y; /* x=0,1,2....,wx-1; y=0,1,2,....,wy-1 */
int n; /* n=0: =1: 生物1 =2:生物2 =3:植物性食物 =4:障碍物 =5:动物性食物 */
{
int gx,gy,i,j;
unsigned char col;
gx=SX1+5*x;gy=SY1+5*y;
for(i=0;i<5;i++)
for(j=0;j<5;j++)
{ switch(n)
{ case 0: col=0; break;
case 1: col=life1[j] [ i]*2; break;
case 2: col=life2[j] [ i]*4; break;
case 3: col=food1[j] [ i]*6; break;
case 4: col=7; break;
case 5: col=food2[j] [ i]*11;
}
g_pset(gx+j,gy+i,col);
}
}
void g_draw_world() /* 显示虚拟环境画面 */
{
int i,j;
for(i=0;i<wy;i++)
for(j=0;j<wx;j++)
g_disp_unit(j,i,world[j] [ i]);
}
void g_draw_frame(x1,y1,x2,y2,c1,c2,c3,c4,text)
int x1,y1,x2,y2,c1,c2,c3,c4;
char *text;
{ int n,x3;
g_rectangle(x1,y1,x2,y2,c1,1);
g_rectangle(x1,y1,x2,y2,c2,0);
g_rectangle(x1,y1,x2,y1+16,c3,1);
g_rectangle(x1,y1,x2,y1+16,c2,0);
n=strlen(text);
x3=x1+((x2-x1-n*8)/2);
disp_hz16(text,x3,y1,c4);
}
void g_init_frames() /* 初始化画面 */
{
int i,j,cx,cy,x,y;
char text[17];
g_draw_frame(0,0,639,399,15,0,4,15,
"基于遗传算法的人工生命模拟");
g_draw_frame(0,16,320,170,7,0,8,15,"设定参数");
y=48;
setcolor(9);
disp_hz16("植物食物限制时间",16,y,15);
sprintf(text,"%d",TL1);
g_text(200,y+8,4,text);
y=y+24;
setcolor(9);
disp_hz16("动物食物限制时间",16,y,15);
sprintf(text,"%d",TL2);
g_text(200,y+8,4,text);
y=y+24;
setcolor(9);
disp_hz16("植物食物每代生成个数",16,y,15);
sprintf(text,"%d",NEWFOODS);
g_text(200,y+8,4,text);
y=y+24;
setcolor(9);
disp_hz16("变异概率",16,y,15);
i=(int)(MUTATION*100.0);
sprintf(text,"%d",i);
g_text(152,y+8,4,text);
g_draw_frame(0,170,320,399,7,0,8,15,"最佳基因型");
x=16;y=194;
setcolor(9);
disp_hz16("SP:物种号........",x,y,15);y=y+16;
disp_hz16("SL:寿命..........",x,y,15);y=y+16;
disp_hz16("VF:视野..........",x,y,15);y=y+16;
disp_hz16("TM:基本移动模式..",x,y,15);y=y+16;
disp_hz16("CM:移动特点......",x,y,15);y=y+16;
disp_hz16("LM:移动能耗......",x,y,15);y=y+16;
disp_hz16("CA:行动特点......",x,y,15);y=y+16;
disp_hz16("CR:善变性........",x,y,15);y=y+16;
disp_hz16("SA:攻击速度......",x,y,15);y=y+16;
disp_hz16("DA:防御能力......",x,y,15);y=y+16;
disp_hz16("LA:攻击能耗......",x,y,15);y=y+16;
disp_hz16("EF:食物吸取效率..",x,y,15);y=y+16;
g_draw_frame(320,16,639,207,7,0,8,15,"虚拟世界");
g_draw_frame(320,207,639,399,7,0,8,15,"世代个体数目变化");
}
void g_init_graph()
/* 个体数进化图初始化 */
{
g_rectangle(GX,GY,GX+GXR,GY+GYR,0,1);
g_rectangle(GX,GY,GX+GXR,GY+GYR,6,0);
setcolor(1);
disp_hz16( "生物 1",GX+5,GY-18,15);
g_line(GX+90,GY-10,GX+110,GY-10,1);
setcolor(4);
disp_hz16( "生物 2",GX+120,GY-18,15);
g_line(GX+205,GY-10,GX+225,GY-10,4);
setcolor(0);
disp_hz16("世代数",GX+168,GY+GYR+10,15);
g_text(GX-25,GY,0,"100");
g_text(GX-14,GY+GYR,0,"0");
}
void g_plot_population(gen_num,n1,n2,n1old,n2old)
int gen_num,n1,n2,n1old,n2old;
{
int x,y,gx,gy,x_old,y_old;
char text[8];
if(gen_num%10==0)
{
x=GX+(gen_num-1)*GSTEP;
g_line(x,GY+1,x,GY+GYR-1,1);
sprintf(text,"%d",gen_num);
if(gen_num<100||gen_num%20==0)
g_text(x-8,GY+GYR+5,15,text);
}
x_old=GX+(gen_num-1)*GSTEP;
x=x_old+GSTEP;
y_old=GY+GYR-n1old;
y=GY+GYR-n1;
g_line(x_old,y_old,x,y,1);
y_old=GY+GYR-n2old;
y=GY+GYR-n2;
g_line(x_old,y_old,x,y,4);
}
void g_disp_genotype() /* 显示最佳个体的遗传基因型 */
{
int i,j,n0,n1,x,y;
unsigned char g[G_LENGTH];
unsigned char bits[12][2]=
{ {0,0},{1,4},{5,6},{7,8},{9,11},{12,12},{13,15},
{16,18},{19,21},{22,24},{25,27},{28,31}};
/* 画面消除 */
g_rectangle(200,187,319,398,7,1);
if(pop_size!=0)
{
/* 获取各遗传因子 */
for(i=0;i<G_LENGTH;i++)
{
n0=0;n1=0;
for(j=0;j<pop_size;j++)
if(gene[j] [ i]==0) n0++;
else n1++;
if(n0>=n1) g [ i]=0; else g [ i]=1;
}
x=220;
for(i=0;i<12;i++)
{
y=202+i*16;
for(j=bits [ i][0];j<=bits [ i][1];j++)
if(g[j]==0)
g_text(x+(j-bits [ i][0])*16,y,4,"0");
else
g_text(x+(j-bits [ i][0])*16,y,4,"1");
}
}
}
void g_disp_char(x,y,x1,y1,x2,y2,v)
int x,y,x1,y1,x2,y2;
unsigned char v;
{
char c[10];
if(x>=x1&& x<=x2-8 && y>=y1 && y<=y2-10)
{
switch(v)
{
case 0: strcpy(c,"0/0");break;
case 1: strcpy(c,"+/0");break;
case 2: strcpy(c,"-/0");break;
case 3: strcpy(c,"x/0");
}
g_text(x,y,15,c);
}
}
void remove_life(n) /* 消除第n个个体 */
int n;
{
iflg[n]=0;
world[iatr[n][0]][iatr[n][1]]=0;
g_disp_unit(iatr[n][0],iatr[n][1],0);
if(food_size+1<=MAX_FOOD)
{
food_size++;
fatr[food_size-1][0]=iatr[n][0];
fatr[food_size-1][1]=iatr[n][1];
fatr[food_size-1][2]=1;
fatr[food_size-1][3]=0;
fflg[food_size-1]=1;
world[iatr[n][0]][iatr[n][1]]=5;
g_disp_unit(iatr[n][0],iatr[n][1],5);
}
}
void remove_food(n) /* 消除第n个食物 */
int n;
{
fflg[n]=0;
world[fatr[n][0]][fatr[n][1]]=0;
g_disp_unit(fatr[n][0],fatr[n][1],0);
}
void make_lives_and_foods() /* 设置虚拟环境中生物与食物 */
{
int x,y,i,j;
pop_size=0;
food_size=0;
for(y=0;y<wy;y++)
for(x=0;x<wx;x++)
{
if(world[x][y]==1||world[x][y]==2)
{
if(pop_size+1<=MAX_POP)
{
pop_size++;
/* 生成遗传因子 */
gene[pop_size-1][0]=world[x][y]-1;
for(i=1;i<G_LENGTH;i++)
gene[pop_size-1] [ i]=random(2);
/* 设定属性 */
iatr[pop_size-1][0]=x;
iatr[pop_size-1][1]=y;
iatr[pop_size-1][2]=70+random(30);
iatr[pop_size-1][3]=random(SL_MIN);
}
}
if(world[x][y]==3||world[x][y]==5)
{
if(food_size+1<=MAX_FOOD)
{
food_size++;
/* 设定属性 */
fatr[food_size-1][0]=x;
fatr[food_size-1][1]=y;
if(world[x][y]==3)
fatr[food_size-1][2]=0;
else
fatr[food_size-1][2]=1;
fatr[food_size-1][3]=random(TL1-1)+1;
}
}
}
}
void find_empty(x,y) /* 寻找虚拟环境中的空处,返回坐标 */
int *x,*y;
{
int ok;
ok=0;
while(ok==0)
{
*x=random(wx);*y=random(wy);
if(world[*x][*y]==0) ok=1;
}
}
void make_world() /* 随机设定人工环境 */
{
int i,j,k,num,x,y;
int ok,overlap;
char choice[3];
double size;
wx=0;
while(wx<10||wx>MAX_WX)
{
setcolor(15);
disp_hz16("虚拟环境长度(10-60)",10,210,20);
gscanf(300,210,4,0,3,"%s",choice);
wx=atoi(choice);
}
wy=0;
while(wy<10||wy>MAX_WY)
{
setcolor(15);
disp_hz16("虚拟环境宽度(10-32)",10,240,20);
gscanf(300,240,4,0,3,"%s",choice);
wy=atoi(choice);
}
for(i=0;i<wy;i++)
for(j=0;j<wx;j++)
if(i==0||i==wy-1||j==0||j==wx-1)
world[j] [ i]=4;
else world[j] [ i]=0;
/* 设定障碍物 */
size=(double)(wx*wy);
num=(int)(size/40.0);
if(num>MAX_POP) num=MAX_POP;
for(i=0;i<num;i++)
{
find_empty(&x,&y);
world[x][y]=4;
}
num=(int)(size/5.0);
if(num>MAX_FOOD) num=MAX_FOOD;
for(i=0;i<num;i++)
{
ok=0;
while(ok==0)
{
x=random(wx);y=random(wy);
if((world[x][y]!=4) &&
(world[x][y-1]==4 || world[x][y+1]==4 ||
world[x-1][y]==4 || world[x+1][y]==4))
{ world[x][y]=4;
ok=1;
}
}
}
for(y=0;y<wy;y++)
for(x=0;x<wx;x++)
if(world[x][y]==0)
{
num=0;
for(i=-1;i<=1;i++)
for(j=-1;j<=1;j++)
if(get_world(x+j,y+i)==4)
num++;
if(num>=6) world[x][y]=4;
}
/* 设定生物 */
num=(int)(size*R_LIFE);
for(i=0;i<num;i++)
{ find_empty(&x,&y);
world[x][y]=random(2)+1;
}
/* 设定食物 */
num=(int)(size*R_FOOD);
for(i=0;i<num;i++)
{
find_empty(&x,&y);
world[x][y]=3;
}
}
void load_world_file() /* 读取虚拟环境数据文件设定 */
{
FILE *fopen(),*fpt;
char st[100],c;
int i,j;
if((fpt=fopen("//ga//world","r"))==NULL) exit(-1);
else
{
fscanf(fpt,"%d",&wx);
fscanf(fpt,"%d",&wy);
for(i=0;i<wy;i++)
for(j=0;j<wx;j++)
fscanf(fpt,"%d",&world[j] [ i]);
fclose(fpt);
}
}
int get_world(x,y) /*坐标(x,y)处环境值 */
int x,y;
{
if(x>=0 && x<wx && y>=0 && y<wy)
return(world[x][y]);
else
return(-1);
}
int decode_gene(n,sb,bw) /* 第n个个体基因型解码 */
int n,sb,bw; /* sb开始位 bw位长 */
{
int i,sum;
sum=0;
for(i=sb;i<sb+bw;i++)
sum=sum*2+gene[n] [ i];
return(sum);
}
void move_pos(n,x1,y1,x2,y2) /* 个体n从(x1,y1)移动到(x2,y2) */
int n,x1,y1,x2,y2;
{
int sp,loss;
loss=decode_gene(n,12,1)+1; /* 移动消耗 */
iatr[n][2]=iatr[n][2]-loss; /* 内部能量更新 */
if(iatr[n][2]<=0) remove_life(n);
else
{
/* 个体属性更新 */
iatr[n][0]=x2;iatr[n][1]=y2; /* x,y坐标更新 */
/* 显示更新 */
sp=gene[n][0]+1;
g_disp_unit(x1,y1,0); /* 当前位置(x,y)图形消除 */
world[x1][y1]=0;
g_disp_unit(x2,y2,sp); /* 新位置图形表示 */
world[x2][y2]=sp;
}
}
void move_randomly(n) /* 个体n按照移动模式随机移动 */
int n;
{
/* 基本移动模式1 */
int pat1[8][2]={{1,0},{1,1},{0,1},{-1,1},
{-1,0},{-1,-1},{0,-1},{1,-1}};
/* 基本移动模式2与3 */
int pat2_3[2][4][2]={{{1,0},{0,1},{-1,0},{0,-1}},
{{1,1},{-1,1},{-1,-1},{1,-1}}};
int pat,x1,y1,x2,y2,rndnum;
pat=decode_gene(n,7,2);
/* pat(0,1,2,3): 表示基本移动模式 */
x1=iatr[n][0]; /* 当前x坐标 */
y1=iatr[n][1]; /* 当前y坐标 */
if(pat<=1) /* 基本移动模式1 */
{
rndnum=random(8);
x2=x1+pat1[rndnum][0]; /* 移动目的点x坐标 */
y2=y1+pat1[rndnum][1]; /* 移动目的点y坐标 */
}
else /* 基本移动模式2与3 */
{
rndnum=random(4);
x2=x1+pat2_3[pat-2][rndnum][0];
y2=y1+pat2_3[pat-2][rndnum][1];
}
if(x2>=0 && x2<wx && y2>=0 && y2<wy)
if(get_world(x2,y2)==0)
move_pos(n,x1,y1,x2,y2);
/* 非法目的点的场合不作移动 */
}
void move_individual(n) /* 个体n移动 */
int n;
{
int cx,cy,dx,dy,sp,vf,sumx,sumy;
int i,j,a,sgn[3],num;
double vect[8][2]={{1,0},{1,1},{0,1},{-1,1},
{-1,0},{-1,-1},{0,-1},{1,-1}};
double vx,vy,d1,d2;
double _cos,cos_max;
cx=iatr[n][0]; /* 当前x坐标 */
cy=iatr[n][1]; /* 当前y坐标 */
sp=decode_gene(n,0,1)+1; /* 生物种1和2 */
for(i=0;i<3;i++) /* 移动特点CM */
{
sgn [ i]=decode_gene(n,9+i,1);
if(sgn [ i]==0) sgn [ i]=-1;
}
sumx=0;sumy=0;num=0;
vf=decode_gene(n,5,2)+1; /* 视野 */
for(i=-vf;i<=vf;i++)
for(j=-vf;j<=vf;j++)
{
if(i!=0||j!=0)
{
a=get_world(cx+j,cy+i);
if(a==1||a==2) /* 生物 1和2 */
{ num++;
if(a==sp) /* 同种生物 */
{
sumx=sumx+sgn[0]*j;
sumy=sumy+sgn[0]*i;
}
else /* 异种生物 */
{
sumx=sumx+sgn[1]*j;
sumy=sumy+sgn[1]*i;
}
} else
if(a==3||a==5) /* 食物 */
{
num++;
sumx=sumx+sgn[2]*j;
sumy=sumy+sgn[2]*i;
}
}
}
if(num!=0) /* 视野内有其他生物和食物时 */
{
vx=(double)sumx/(double)num;
vy=(double)sumy/(double)num;
if(vx!=0||vy!=0)
{
cos_max=-1.0;
j=0;
for(i=0;i<8;i++)
{
d1=sqrt(vx*vx+vy*vy);
d2=sqrt(vect [ i][0]*vect [ i][0]+vect [ i][1]*vect [ i][1]);
_cos=(vx*vect [ i][0]+vy*vect [ i][1])/d1/d2;
if(_cos>cos_max)
{
cos_max=_cos;j=i;
}
}
dx=cx+(int)vect[j][0];
dy=cy+(int)vect[j][1];
if(dx>=0 && dx<wx && dy>=0 && dy<wy)
if(world[dx][dy]==0)
move_pos(n,cx,cy,dx,dy);
}
else move_randomly(n);
}
else move_randomly(n);
/* 视野内有其他生物和食物时 */
}
void act1_attack(n) /* 个体 n攻击行动范围内的其他生物个体 */
int n;
{
int sft[8][2]={{1,0},{1,1},{0,1},{-1,1},
{-1,0},{-1,-1},{0,-1},{1,-1}};
int x1,y1,x2,y2,n2;
int found,rndnum;
double attack1,attack2,sa1,sa2,da1,da2,rnd1,rnd2,La1,La2;
x1=iatr[n][0];y1=iatr[n][1];
/* 获得攻击对象的坐标(x2,y2) */
found=0;
while(found==0)
{
rndnum=random(8);
x2=x1+sft[rndnum][0];
y2=y1+sft[rndnum][1];
if(get_world(x2,y2)==1||get_world(x2,y2)==2)
found=1;
}
/* 检查攻击对象个体号n2 */
found=0;n2=0;
while(found==0)
{
if(iatr[n2][0]==x2 && iatr[n2][1]==y2 && iflg[n2]==1)
found=1; else n2++;
}
/* 计算双方的 Attack量 */
sa1=(double)decode_gene(n,19,3);
da1=(double)decode_gene(n,22,3);
sa2=(double)decode_gene(n2,19,3);
da2=(double)decode_gene(n2,22,3);
rnd1=(double)random(1001)/1000.0;
rnd2=(double)random(1001)/1000.0;
attack1=(double)iatr[n][2]+sa1*20.0/7.0*rnd1+da1*20.0/7.0*rnd2;
rnd1=(double)random(1001)/1000.0;
rnd2=(double)random(1001)/1000.0;
attack2=(double)iatr[n2][2]+sa2*20.0/7.0*rnd1+da2*20.0/7.0*rnd2;
/* 减少内部能量 */
La1=decode_gene(n,25,3);
La2=decode_gene(n2,25,3);
rnd1=(double)random(1001)/1000.0;
iatr[n][2]=iatr[n][2]-(int)((double)La1*rnd1);
rnd2=(double)random(1001)/1000.0;
iatr[n2][2]=iatr[n2][2]-(int)((double)La2*rnd2);
if(attack1>=attack2) /* 胜者: n 败者:n2 */
iatr[n2][2]=iatr[n2][2]-40;
else /* 胜者: n2 败者:n */
iatr[n][2]=iatr[n][2]-40;
if(iatr[n][2]<=0) remove_life(n);
if(iatr[n2][2]<=0) remove_life(n2);
}
void act2_eat(n) /* 个体n获取行动范围内的食物 */
int n;
{
int sft[8][2]={{1,0},{1,1},{0,1},{-1,1},
{-1,0},{-1,-1},{0,-1},{1,-1}};
int x1,y1,x2,y2,n2,ef;
int found,rndnum;
x1=iatr[n][0];y1=iatr[n][1];
/* 获取食物位置(x2,y2) */
found=0;
while(found==0)
{
rndnum=random(8);
x2=x1+sft[rndnum][0];
y2=y1+sft[rndnum][1];
if(get_world(x2,y2)==3||get_world(x2,y2)==5)
found=1;
}
/* 增加内部能量 */
ef=decode_gene(n,28,4); /* 食物吸取效率 */
iatr[n][2]=iatr[n][2]+(int)(40.0*(50.0+(double)ef*50.0/15.0)/100.0);
if(iatr[n][2]>100) iatr[n][2]=100;
/* 检查食物号n2 */
found=0;n2=0;
while(found==0)
{
if(fatr[n2][0]==x2 && fatr[n2][1]==y2 && fflg[n2]==1)
found=1; else n2++;
}
remove_food(n2);
}
void act3_makechild(n) /* 个体n与行动范围内的其他生物个体交配产生子个体 */
int n;
{
int i,j,k,x,y,x2,y2,found,n2,trial;
int x3,y3;
double rnd;
if(pop_size+1<=MAX_POP)
{
x=iatr[n][0];y=iatr[n][1];
found=0;
while(found==0)
{
x2=x+random(3)-1;
y2=y+random(3)-1;
if(x2!=x||y2!=y)
if(get_world(x2,y2)==gene[n][0]+1);
found=1;
}
/* 检查交配对象个体号n2 */
found=0; n2=0;
while(found==0)
{
if((iatr[n2][0]==x2 || iatr[n2][1]==y2) && iflg[n2]==1)
found=1; else n2++;
if(n2>=pop_size-1) return;
}
/* 确定产生个体位置 */
found=0;trial=0;
while(found==0 && trial<50)
{
i=random(3)-1;j=random(3)-1;
k=random(2);
if(k==0) { x3=x+i;y3=y+j;}
else { x3=x2+i;y3=y2+j;}
if(get_world(x3,y3)==0) found=1;
trial++;
}
if(found==1)
{
/* 个体 n与个体 n2产生子个体 */
pop_size++;
/* 均匀交叉 */
uni_crossover(gene,n,n2,pop_size-1,0.5,G_LENGTH);
/* 变异 */
for(i=1;i<G_LENGTH;i++)
{
rnd=random(10001)/10000.0;
if(rnd<=MUTATION)
if(gene[pop_size-1] [ i]==1)
gene[pop_size-1] [ i]=0;
else gene[pop_size-1] [ i]=1;
}
/* 交配后父个体能量减少 */
iatr[n][2]=iatr[n][2]-45;
if(iatr[n][2]<=0) remove_life(n);
iatr[n2][2]=iatr[n2][2]-45;
if(iatr[n2][2]<=0) remove_life(n2);
/* 子个体属性输入 */
iatr[pop_size-1][0]=x3;
iatr[pop_size-1][1]=y3;
iatr[pop_size-1][2]=100;
iatr[pop_size-1][3]=0;
iflg[pop_size-1]=1;
/* 子个体画面表示 */
world[x3][y3]=gene[pop_size-1][0]+1;
g_disp_unit(x3,y3,gene[pop_size-1][0]+1);
}
}
}
void act_individual(n) /* 为行动范围内的其他生物和食物决定行动 */
int n;
{
int i,j,k,pattern,action,cr,ca;
int act[3]; /* act[0]:攻击 act[1]:获取食物 act[2]:交配 */
int pat[6][3]={{1,2,3},{1,3,2},{2,1,3},
{3,1,2},{2,3,1},{3,2,1}};
/* pat:行动优先顺序 {攻击,获取食物,交配} */
int sp;
double rnd;
sp=decode_gene(n,0,1)+1;
for(i=0;i<3;i++) act [ i]=0;
for(i=-1;i<=1;i++)
for(j=-1;j<=1;j++)
{
if(i!=0||j!=0)
{
k=get_world(iatr[n][0]+j,iatr[n][1]+i);
if(k==1||k==2) act[0]=1;
if(k==3||k==5) act[1]=1;
if(k==sp) act[2]=1;
}
}
cr=decode_gene(n,16,3);
rnd=(double)random(10001)/10000.0;
if(rnd<=(double)cr/7.0)
{
action=random(3);
while(act[action]==0)
action=random(3);
}
else
{
ca=decode_gene(n,13,3); /* ca行动特点 */
if(ca<3) pattern=0;else pattern=ca-2;
/* 基本行动模式pattern 0-5 */
i=0;
action=pat[pattern] [ i]-1;
while( act[action]==0)
{
i++;
action=pat[pattern] [ i]-1;
}
}
switch(action+1)
{
case 1: act1_attack(n);break;
case 2: act2_eat(n);break;
case 3: act3_makechild(n);
}
}
void init_flags() /* 状态标志初始化 */
{
int i;
for(i=0;i<pop_size;i++) iflg [ i]=1;
for(i=0;i<food_size;i++) fflg [ i]=1;
}
void act_lives() /* 改变状态(移动或行动) */
{
int i,j,k,x,y,move,a;
for(i=0;i<pop_size;i++)
{
if(iflg [ i]==1)
{
move=1;
for(j=-1;j<=1;j++)
for(k=-1;k<=1;k++)
{
if(j!=0||k!=0)
{
a=get_world(iatr [ i][0]+k,iatr [ i][1]+j);
if(a==1||a==2||a==3||a==5)
move=0;
}
}
if(move==1)
move_individual(i);
else
act_individual(i);
}
}
}
void increase_age() /* 个体年龄增1 */
{
int i,j,s;
for(i=0;i<pop_size;i++)
{
if(iflg [ i]==1)
{
j=decode_gene(i,1,4);
s=SL_MIN+j;
iatr [ i][3]++;
if(iatr [ i][3]>s)
remove_life(i);
}
}
}
void increase_frsh() /* 食物新鲜度增1 */
{
int i;
for(i=0;i<food_size;i++)
if(fflg [ i]==1)
{
fatr [ i][3]++;
if((fatr [ i][2]==0 && fatr [ i][3]>TL1)||
(fatr [ i][2]==1 && fatr [ i][3]>TL2))
remove_food(i);
}
}
void gabage_col() /* 死去个体及消减食物清除*/
{
int i,j;
int new_pop,new_food;
/* 检查食物 */
new_food=0;
for(i=0;i<food_size;i++)
if(fflg [ i]==1)
{
new_food++;
for(j=0;j<4;j++)
fatr[new_food-1][j]=fatr [ i][j];
}
food_size=new_food;
/* 检查个体 */
new_pop=0;
for(i=0;i<pop_size;i++)
if(iflg [ i]==1)
{
new_pop++;
/* 遗传基因复制 */
for(j=0;j<G_LENGTH;j++)
gene[new_pop-1][j]=gene [ i][j];
/* 属性复制 */
for(j=0;j<4;j++)
iatr[new_pop-1][j]=iatr [ i][j];
}
pop_size=new_pop;
}
void make_foods() /* 产生一代中植物性食物 */
{
int i,x,y;
for(i=0;i<NEWFOODS;i++)
{
if(food_size+1<=MAX_FOOD)
{
food_size++;
find_empty(&x,&y);
fatr[food_size-1][0]=x;
fatr[food_size-1][1]=y;
fatr[food_size-1][2]=0; /* 植物性 */
fatr[food_size-1][3]=0;
fflg[food_size-1]=1;
world[x][y]=3;
g_disp_unit(x,y,3);
}
}
}
void calc_population(n1,n2) /* 计算生物1和2 的个体数 */
int *n1,*n2;
{
int i,p1,p2;
p1=0;p2=0;
if(pop_size>0)
for(i=0;i<pop_size;i++)
if(gene [ i][0]==0) p1++; else p2++;
*n1=p1;
*n2=p2;
}
main() /* 主程序 */
{
int i,work;
int n1,n2,n1old,n2old;
char choice[2];
randomize();
/* 图形界面初始化 */
g_init();
settextstyle(0,0,4);
gprintf(220,20,4,0,"ALIFE");
setcolor(9);
disp_hz24("基于遗传算法的人工生命模拟",150,60,25);
setcolor(15);
disp_hz16("人工环境及生物分布",10,160,20);
disp_hz16("1:随机产生 2: 读文件产生 ==>",10,190,20);
gscanf(300,190,15,1,4,"%s",choice);
work=atoi(choice);
if(work==2) load_world_file();else make_world();
make_lives_and_foods();
/*状态初始化 */
init_flags();
/*计算个体数 */
calc_population(&n1old,&n2old);
/*生成初始画面*/
g_init_frames();
/*虚拟世界画面*/
g_draw_world();
/* 显示初始图形 */
g_init_graph();
for(i=1;i<121;i++)
{
/*状态初始化 */
init_flags();
/* 改变状态(移动或行动) */
act_lives();
/* 个体年龄增加 */
increase_age();
/* 食物新鲜度增加 */
increase_frsh();
/*死去个体及消减食物清除*/
gabage_col();
/*产生新的食物 */
make_foods();
/* 求生物1和2 的个体数 */
calc_population(&n1,&n2);
/* 个体数变化的图形更新 */
g_plot_population(i,n1,n2,n1old,n2old);
n1old=n1;n2old=n2;
/* 显示最佳遗传基因 */
g_disp_genotype();
}
setcolor(9);
disp_hz16("回车键结束",10,430,20);
getch();
}
- 遗传算法
- 遗传算法
- 遗传算法
- 遗传算法
- 遗传算法
- 遗传算法
- 遗传算法
- 遗传算法
- 遗传算法
- 遗传算法
- 遗传算法
- 遗传算法
- 遗传算法
- 遗传算法
- 遗传算法
- 遗传算法
- 遗传算法
- 遗传算法
- Oxygen xml editor v9.1.0 + plugins | 54.8 Mb
- Quick Memory Editor 4.0
- grub2研究(2)
- 创业,却发现自己过于愚蠢
- MySQL可靠性方案分析与比较
- 遗传算法
- 期待。。。
- IIS中图片无法浏览的问题
- 无心插柳-在vs2005中编译GCC4
- lex bison
- 程序员读懂“新劳法” 敢问公司“谁怕谁”(1)
- Javascript学习--进度条
- Java IDE实用对比:Eclipse、NetBeans、IntelliJ
- 宽屏 WARCRAFT III 全屏的方法