遗传算法C语言源码

来源:互联网 发布:欧莱雅润发精油 知乎 编辑:程序博客网 时间:2024/06/05 03:57

遗传算法是上学时曾经研究过的算法,它是一种基于基因遗传思想的快速搜索遍历算法。简单理解,它就是比一般的盲搜索和其他的一些搜索快的算法。其主要目的就是为了能快速准确搜索所求的值,用于求解一些复杂的数值应用,以及一些实时性要求高的算法应用中。以下是以前练习过的代码,欢迎有需要的同学学习交流。

include <stdio.h>include <string.h>include <stdlib.h>include <ctime>include <math.h>define N 30000000000define PI 3.14159265define MIN_(a,b) ((a)>(b)?(b):(a))//定义求最小值函数MIN_(a,b) define SIZE  50define MAXGEN  50define P_CORSS 0.75define P_MUTATION 0.05define LEN 22typedef struct node//定义结构体,表示染色体,x是染色体二进制编码,fitness是该染色体的适应值,fitsum是当前所有染色体的适应值的总和{  char x[LEN];  double fitness,fitsum;}node;node cur[SIZE],next[SIZE],max,min;//定义结构体数组,有当前染色体种群,下一代染色体种群,以及最优和最差染色体。double randd(){  return (double)rand()/RAND_MAX;//产生0-1之间随机数, RAND_MAX其值至少为32767,rand()在0-MAX之间}int randi(int k){  return (int)(randd()*k+0.5);//返回接近k大小的随机值}//计算当前种群中各个个体的适应度 void cal_fitness(){  int i,j,k;  double d;  for(i=0;i<SIZE;i++)  {    k=0;    for(j=LEN-1;j>=0;j--) k=(k<<1)+cur[i].x[j];;//该循环用于将染色体二进制数转成十进制,<<是左移运算,x[j]是染色体i的第j位    d=(double)k/N*100-50;//用上面的k产生一个浮点数d,作为函数自变量x的值    cur[i].fitness=d+10*sin(5*d)+7*cos(4*d);            //计算每个染色体的适应值  //////// //函数y= x+10*sin(5*x)+7*cos(4*x)//////////////     cur[i].fitsum=i>0?(cur[i].fitness+cur[i-1].fitsum):(cur[0].fitness);//计算所有适应值的总和,里面有迭代过程,就是若i=3,则cur[3].fitsum=cur[3].fitsum+cur[2].fitsum+cur[1].fitsum+cur[0].fitsum.  }}void init()//初始化染色体种群,共SIZE个,每个都是二进制LEN长度的串{  int tmp;  for(int i=0;i<SIZE;i++)  {    tmp=randi(N);//用randi函数产生一个大概N那么大的随机数    for(int j=0;j<LEN;j++)    {      cur[i].x[j]=tmp%2;//用temp对2取余,初始化每个染色体的每个位,共LEN位;一个数不是奇数就是偶数,对2取余得0或1,从而产生像001001010...11010001这样的串      tmp=tmp>>1;//右移tmp,就是将temp缩小,使tmp值变化    }  }  cal_fitness();//计算当前种群各个个体的适应度 }int sel()//选择种群中某个染色体{  double p=randd();  double sum=cur[SIZE-1].fitsum;//全部染色体的适应值总和  for(int i=0;i<SIZE;i++)  {    if(cur[i].fitsum/sum>p) return i;//如果当前适应总值/全部总值大于随机数p,也就是当前适应总值不为0,不太差时,返回这个i值,循环停止  }}//换代 void tran(){  int i,j,pos;  //找当前种群最优个体     max=cur[0];  for(i=1;i<SIZE-1;i++)  {    if(cur[i].fitness>max.fitness)  max=cur[i];//记录种群中的最优染色体为max  }  for(int k=0;k<SIZE;k+=2)  {    //选择交叉个体     i=sel();//用sel函数挑选一个个体,染色体号为i    j=sel();//同上,再选择个个体,号为j    //选择交叉位置     pos=randi(LEN-1);//随机产生个LEN-1左右的数pos,如18,19,21等    //交叉    if(randd()<P_CORSS)//如果randd()产生的随机数(在0-1之间)小于设定的交叉率P_CORSS    {      memcpy(next[k].x,cur[i].x,pos);//提取染色体i的前pos位赋给下一代种群next的第k个染色体.——函数memcpy(&a,&b,n)用于从&b的位置开始数n个长度的数据拷贝赋给&a;       memcpy(next[k].x+pos,cur[j].x+pos,LEN-pos);//提取染色体j的 后面LEN-pos位赋给next的第k个染色体,结合上面,从而拼成一个新的染色体      memcpy(next[k+1].x,cur[j].x,pos);//同样的方式给next的第k+1染色体赋值,这回换过来生成这个值,即提取j的前pos位数据 + i的后LEN-pos位数据      memcpy(next[k+1].x+pos,cur[i].x+pos,LEN-pos);    }    else//否则不交叉,    {      memcpy(next[k].x,cur[i].x,LEN);      memcpy(next[k+1].x,cur[j].x,LEN);    }    //变异    if(randd()<P_MUTATION)//如果一随机数小于设定的变异率P_MUTATION,则执行变异操作    {      pos=randi(LEN-1);//仍然是从中间找个位置,执行变异      next[k].x[pos]^=next[k].x[pos];// ^=按位异或后赋值函数,相同为0不同为1,此处是将第pos位上的值(不论是0或1)定为0      pos=randi(LEN-1);      next[k+1].x[pos]^=next[k+1].x[pos];//同样将下一代next的第k+1个染色体的第pos位也变为0;??最好应该是0变1,1变0...,但这样也行,进化稍慢点    }  }  //找下一代的最差个体   min=next[0],j=0;  for(i=1;i<SIZE-1;i++)  {    if(next[i].fitness<min.fitness)  min=next[i],j=i;//用j记录最差染色体号  }  //用上一代的最优个体替换下一代的最差个体  next[j]=max;  memcpy(cur,next,sizeof(cur));//把整个改良过的(经过交叉,变异,替换等操作的)next代的值赋给当前种群cur,供下一次循环优化  cal_fitness();}//打印个体适应度和二进制编码 void print(node tmp){  printf("%.6lf",tmp.fitness);  for(int i=0;i<LEN;i++)  printf(" %d",tmp.x[i]);  printf("\n");}//打印种群void printcur(){  for(int i=0;i<SIZE;i++) print(cur[i]);} void GA(){  int cnt=0;  double ans;  while(cnt++<MAXGEN)//当计数值cnt小于设定的最大进化次数MAXGEN,执行换代操作  {    tran();  }  ans=cur[0].fitness;  for(int i=1;i<SIZE;i++) ans=MIN_(ans,cur[i].fitness);//找出函数最小值,打印输出(应设定的是求函数最小值)  printf("%.6lf\n",ans);}int main(){  srand((unsigned)time(NULL));//初始化随机数种子产生器,为使程序中每次的rand()函数产生的随机数不一样  init();//初始化种群  GA();//遗传换代操作  system("pause"); //输出结果在屏幕,而不是一闪而过  return 0;}
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 大便排不出去怎么办 婴儿三个没大便怎么办 三天不上大便怎么办 婴儿几天没大便怎么办 排便不好肚子大怎么办 三天不拉大便怎么办 几天不拉大便怎么办 七天不大便该怎么办 新生儿嘴巴很干怎么办 一岁宝宝过敏怎么办 母乳喂养宝宝不吃奶瓶怎么办 宝宝吃奶特别急怎么办 宝宝吃奶粉消化不良怎么办 喝羊奶大便干燥怎么办 宝宝换奶粉发烧怎么办 婴儿吃了蛋白怎么办 新生儿吃了蜂蜜怎么办 婴儿吃蜂蜜中毒怎么办 宝宝吃蜂蜜中毒怎么办 宝宝对蛋清过敏怎么办 宝宝吃蛋清过敏怎么办 婴儿吃蛋清过敏怎么办 初生婴儿拉水怎么办 婴儿鸡蛋过敏了怎么办 婴儿鸡蛋白过敏怎么办 母牛产后涨奶怎么办 宝宝吃奶时间长边吃边睡怎么办 宝宝吃海鲜过敏怎么办 小孩吃虾过敏怎么办 三个月婴儿不吃奶粉怎么办 宝宝秋季腹泻发烧怎么办 婴儿肚子有积食怎么办 小孩眼睛有点斜怎么办 孕妇血糖高便秘怎么办 宝宝蛋清过敏了怎么办 婴儿对鸡蛋过敏怎么办 宝宝断奶喝酸奶怎么办 宝宝被异物卡住怎么办 宝宝夜里膝盖痛怎么办 宝宝吃蛋白过敏怎么办 身体蛋白率低怎么办