关于遗传算法
程序代码:
#include <stdio.h> #include <math.h> #include <stdlib.h> #include <time.h> #define SUM 20 //定义群体的染色体数量 #define MAXloop 1200 //最大循环次数 #define error 0.01 //若两次最优值之差小于次数则认为结果没有改变 #define crossp 0.7 //交叉概率,所选中的双亲按此概率进行交叉 #define mp 0.04 //变异概率 struct gen //定义染色体 { int info; //染色体结构,用一整型数的后14位作为染色体编码 float suitability; //此染色体所对应的适应度函数值,即表达式的值 }; struct gen gen_group[SUM]; //定义含有20个染色体的种群 struct gen gen_new[SUM]; //定义含有20个染色体的种群,记录交叉产生的子代染色体 struct gen gen_result; //记录上一轮循环中得到的最优的染色体 int result_unchange_time; //当相邻两轮得到的最优值对应的适应度 //之差小于error时其值增1,反之清零 struct log //形成链表,记录每次循环所产生的最优的适应度 { float suitability; struct log *next; }llog, *head, *end; int log_num; // 链表长度 void initiate(void); //初始化函数,负责产生初始种群 void evaluation(int flag); //评估染色体的适应度,进行排序 void cross(void); //交叉函数 void selection(void); //选择函数 int record(void); //记录每次循环所产生的最优解并判断循环是否终止 void mutation(void); //编译函数 void showresult(int); //显示结果 int randsign(float p); //按概率p随机产生0、1其值为的概率为p int randbit(int i, int j); //随机产生一个在i,j两个数之间的整数 int randnum(void); //随机产生一个14个基因组成的染色体 int createmask(int a); //用于交叉操作 int convertionD2B(float x); //对现实解空间的可能解x进行二进制编码 float convertionB2D(int x); //将二进制编码x转化为现实解空间的值 void main() { int i,flag; flag = 0; initiate(); evaluation(0); for(i=0; i<MAXloop; i++) { cross(); evaluation(1); selection(); if(record()==1) { flag == 1; break; } mutation(); } showresult(flag); } /*函数三个功能:1.初始化随机列表 2.建立规模SUM的初始种群 3.建立log链表头, 其中指针head记录链表头的位置,end始终指向链表的尾部*/ void initiate(void) { int i, stime; long ltime; ltime = time(NULL); stime = (unsigned)ltime/2; srand(stime); for(i=0; i<SUM; i++) gen_group[i].info = randnum(); gen_result.suitability = 1000; result_unchange_time = 0; head = end = (struct log *)malloc(sizeof(llog)); if(head == NULL) { printf("\n内存不够"); exit(1); } end->next = NULL; log_num = 1; } void evaluation(int flag) { int i, j; struct gen *genp; int gentinfo; float gentsuitability; float x; if(flag == 0) genp = gen_group; else genp = gen_new; for(i=0; i<SUM; i++) { x = convertionB2D(genp[i].info); genp[i].suitability = x*(x*(x*(x*(x*(x-10)-26)+344)+193)-1846)-1680; } for(i=0; i<SUM-1; i++) { for(j=i+1; j<SUM; j++) { if(genp[i].suitability > genp[j].suitability) { gentinfo = genp[i].info; genp[i].info = genp[j].info; genp[j].info = gentinfo; gentsuitability = genp[i].suitability; genp[i].suitability = genp[j].suitability; genp[j].suitability = gentsuitability; } } } } /*cross由三部分组成:1.随机选择将要进行交叉的染色体对,保证种群中的每一个 染色体都有唯一一次交叉的机会,2.按crossp的概率对选择的染色体对进行交叉操作 3.为进行交叉的染色体直接复制作为子染色体。 首先由ranbit()进行交叉位 createmask()返回一个交叉位以右皆为1的二进制数,赋值给mask1,mask2为交叉 以左皆为1的二进制数,它们分别与父染色体gen_group[i].info gen_group[j].info 进行操作,所得的结果的和即为交叉的结果*/ void cross(void) { int i, j, k; int mask1, mask2; int a[SUM]; for(i=0; i<SUM; i++) a[i] = 0; k = 0; for(i=0; i<SUM; i++) { if(a[i]==0) { for(;;) { j = randbit(i+1, SUM-1); if(a[j] == 0) break; } if(randsign(crossp)==1) { mask1 = createmask(randbit(0, 14)); mask2 = -mask1; gen_new[k].info = (gen_group[i].info) & mask1 + (gen_group[j].info) & mask2; gen_new[k+1].info = (gen_group[i].info) & mask2 + (gen_group[j].info) & mask1; k = k + 2; } else { gen_new[k].info = gen_group[i].info; gen_new[k+1].info = gen_group[j].info; k = k + 2; } a[i] = a[j] = 1; } } } /*函数从父代种群和子代种群中选择最优的染色体组成新的父代种群。由于两个种群 都已进行了排序,因此只需找到子代种群中的第t个个体使其适应度函数值满足: 大于父代中种群中的第NUM-t个个体,并小于父代的第NUM-t+1个个体,然后用子代种群中 的前t个个体代替父代种群的后t个个体即可。*/ void selection(void) { int i, j, k; j = 0; i = SUM/2 - 1; if(gen_group[i].suitability < gen_new[i].suitability) { for(j=1; j<SUM/2; j++) { if(gen_group[i+j].suitability > gen_new[i-j].suitability) break; } } else if(gen_group[i].suitability > gen_new[i].suitability) { for(j = -1; j>-SUM/2; j--) { if(gen_group[i+j].suitability<=gen_new[i-j].suitability) break; } } for(k=j; k<SUM/2+1; k++) { gen_group[i+k].info = gen_new[i-k].info; gen_group[i+k].suitability = gen_new[i-k].suitability; } } /*两个任务:1.用链表记录各轮循环中的最优值,2.判断是否满足循环停止条件, 当两次循环的适应度的差小于error时,result——unchange-time的值加1, 若result——unchange-time达到20时表示已经搜索到最优值,返回1,若适应度 差大于等于error则将result——unchange——time清零,并记录本轮最优,函数返回0*/ int record(void) { float x; struct log *r; r = (struct log*)malloc(sizeof(llog)); if(r==NULL) { printf("\n内存不够!\n"); exit(1); } r->next = NULL; end->suitability = gen_group[0].suitability; end->next = r; end = r; log_num++; x = gen_result.suitability - gen_group[0].suitability; if(x < 0) x = -x; if(x < error) { result_unchange_time++; if(result_unchange_time >= 20) return 1; } else { gen_result.info = gen_group[0].info; gen_result.suitability = gen_group[0].suitability; result_unchange_time = 0; } return 0; } void mutation(void) { int i, j, m; int gentinfo; float x; float cmp; float gentsuitablitity; cmp = 1 - pow(i-mp, 11); for(i=0; i<SUM; i++) { if(randsign(cmp)==1) { j = randbit(0, 14); m = 1<< j; gen_group[i].info = gen_group[i].info^m; x = convertionB2D(gen_group[i].info); x = x*(x*(x*(x*(x*(x-10)-26)+344)+193)-1846)-1680; gen_group[i].suitability = x; } } for(i=0; i<SUM-1; i++) { for(j=i+1; j<SUM; j++) { if(gen_group[i].suitability > gen_group[j].suitability) { gentinfo = gen_group[i].info; gen_group[i].info = gen_group[j].info; gen_group[j].info = gentinfo; gentsuitablitity = gen_group[i].suitability; gen_group[i].suitability = gen_group[j].suitability; gen_group[j].suitability = gentsuitablitity; } } } } void showresult(int flag) { int i, j; struct log *logfree; struct log *logprint; logprint = (struct log *)malloc(sizeof(llog)); if(logprint==NULL) { printf("分配内存"); exit(1); } logprint = head; FILE *logf; if(flag == 0) printf("\n已到最大搜索次数,搜索失败!\n"); else { printf("当取值%f时表达式达到最小值为%f\n", convertionB2D(gen_result.info), gen_result.suitability); printf("收敛过程记录与文件log.txt"); if((logf = fopen("log.txt", "w+"))==NULL) { printf("Cannot creat/open file"); exit(1); } for(i=0; i<log_num; i=i+5) { for(j=0; (j<5) & ((i+j)<log_num-1); j++) { fprintf(logf, "%20f", logprint->suitability); logprint = logprint->next; } fprintf(logf, "\n \n"); } } for(i=0; i<log_num; i++) { logfree = head; head = head->next; free(logfree); fclose(logf); } getchar(); } int randsign(float p) { if(rand()>(p*32768)) return 0; else return 1; } int randbit(int i, int j) { int a, l; l = j - i + 1; a = i + rand() * l/32768; return a; } int randnum(void) { int x; x = rand()/2; return x; } float convertionB2D(int x) { float y; y = x; y = (y - 8192)/1000; return y; } int convertionD2B(float x) { int g; g = (x*1000) + 8192; return g; } int createmask(int a) { int mask; mask = (1<<(a+1)) - 1; return mask; } 高手们帮我看看这个遗传算法哪里出错了??? 谢谢!!!