📄 aga.txt
字号:
//采用了保优的选择遗传算法
//终止条件的判断是:到达一定的代数。可改进为:相邻若干代的种群平均适应值的变化来判断。若相邻若干代的种群平均适应值为变化或者是变化
//小于某一阈值,表示算法已经收敛,则退出算法。
//选择算子:轮盘赌选择;
//交叉算子:单点交叉,随机选择计算此适应度值,若大于当前最佳适应度值则降低交叉概率,否则不变;
//变异算子:模板,对于优势个体,除采用低概率变异外,变异位置应采取权值越大,变异概率越小的原则,而对劣势个体则相反.
#include <stdio.h>
#include "malloc.h"
#include <math.h>
#include <string.h>
#include "stdlib.h"
// 全局变量
struct individual //个体
{
unsigned *chrom; // 染色体
double fitness; // 个体适应度
double varible; // 个体对应的变量值
int xsite; // 交叉位置
int parent[2]; // 父个体
int *utility; // 特定数据指针变量
};
struct bestever // 最佳个体
{
unsigned *chrom; // 最佳个体染色体
double fitness; // 最佳个体适应度
double varible; // 最佳个体对应的变量值
int generation; // 最佳个体生成代
};
struct individual *oldpop; // 当前代种群
struct individual *newpop; // 新一代种群
struct bestever bestfit; // 最佳个体
double sumfitness; // 种群中个体适应度累计
double max; // 种群中个体最大适应度
double avg; // 种群中个体平均适应度
double min; // 种群中个体最小适应度
double pcross; // 交叉概率
double pmutation; // 变异概率
int popsize; // 种群大小
int lchrom; // 染色体长度
int chromsize; // 存储一染色体所需字节数
int gen; // 当前世代数
int maxgen; // 最大世代数
int run; // 当前运行次数
int maxruns; // 总运行次数
int printstrings; // 输出染色体编码的判断,0 -- 不输出, 1 -- 输出
int nmutation; // 当前代变异发生次数
int ncross; // 当前代交叉发生次数
double pc1;
double pc2;
double pm1;
double pm2;
int temp_mate1;
int temp_mate2;
// 随机数发生器使用的静态变量
static double oldrand[55];//存储随机数
static int jrand;
static double rndx2;
static int rndcalcflag;
// 输出文件指针
FILE *outfp ;
// 函数定义
void advance_random();
int flip(double);rnd(int, int);
void randomize();
double randomnormaldeviate();
float randomperc(),rndreal(float,float);
void warmup_random(float);
void initialize(),initdata(),initpop();
void initreport(),generation(),initmalloc();
void freeall(),nomemory(char *),report();
void writepop(),writechrom(unsigned *);
void preselect();
void statistics(struct individual *);
void title(),repchar (FILE *,char *,int);
void skip(FILE *,int);
int select();
void objfunc(struct individual *);
int crossover (unsigned *, unsigned *, unsigned *, unsigned *);
void mutation(unsigned *);
void initialize() // 遗传算法初始化
{
// 键盘输入遗传算法参数
initdata();
// 确定染色体的字节长度
chromsize = (lchrom/(8*sizeof(unsigned)));
if(lchrom%(8*sizeof(unsigned))) chromsize++;//如果还有不到一个字节的分配一字节
//分配给全局数据结构空间
initmalloc();
// 初始化随机数发生器
randomize();
// 初始化全局计数变量和一些数值
nmutation = 0;
ncross = 0;
bestfit.fitness = 0.0;
bestfit.generation = 0;
// 初始化种群,并统计计算结果
initpop();
statistics(oldpop);
initreport();
}
void initdata() // 遗传算法参数输入
{
/* char answer[2];
printf("种群大小(50-200):");
scanf("%d", &popsize);
if((popsize%2) != 0)
{
printf( "种群大小已设置为偶数\n");//只有偶数的个体总数才能完成交叉
popsize++;
}
printf("染色体长度(64-1000):");
scanf("%d", &lchrom);
printf("是否输出染色体编码(y/n):");
printstrings=1; // 输出染色体编码的判断,0 -- 不输出, 1 -- 输出
scanf("%s", answer);
if(strncmp(answer,"n",1) == 0) printstrings = 0;
printf("最大世代数(100-300):");
scanf("%d", &maxgen);
printf("交叉率(0.2-0.99):");
scanf("%f", &pcross);
printf("初始变异率(0.01-0.9):");
scanf("%f", &pmutation);
printf("pc1(0.01-0.9):");
scanf("%lf", &pc1);
printf("pc2(pc2>pc1):");
scanf("%lf", &pc2);
printf("调整变异率pm1(0.01-0.9):");
scanf("%lf", &pm1);
printf("调整变异率pm2(pm2>pm1):");
scanf("%lf", &pm2);
run=nmutation=ncross=gen=0;//各变量的初始化
max=min=avg=0.0;*/
popsize=lchrom=100;
printstrings = 0;
pcross=pmutation=0.5;
maxgen=200;
pc1=0.6;
pc2=0.8;
pm1=0.05;
pm2=0.1;
nmutation=ncross=gen=0;
max=min=avg=0.0;
}
void initpop() // 随机初始化种群
{
int j, j1, k, stop;
unsigned mask = 1;
for(j = 0; j < popsize; j++)
{
for(k = 0; k < chromsize; k++)
{
oldpop[j].chrom[k] = 0;//初始化染色体,因为一个字节可存储8个基因
if(k == (chromsize-1))
stop = lchrom - (k*(8*sizeof(unsigned)));
else
stop =8*sizeof(unsigned);
for(j1 = 1; j1 <= stop; j1++)
{
oldpop[j].chrom[k] = oldpop[j].chrom[k]<<1;//左移一位
if(flip(0.5))
oldpop[j].chrom[k] = oldpop[j].chrom[k]|mask;//按位或,即全部赋值为1
}
}
oldpop[j].parent[0] = 0; // 初始父个体信息
oldpop[j].parent[1] = 0;
oldpop[j].xsite = 0;
objfunc(&(oldpop[j])); // 计算初始适应度
}
}
void initreport() // 初始参数输出
{
// void skip();
skip(outfp,1);
printf(" 基本遗传算法参数\n");
printf(" -------------------------------------------------\n");
printf(" 种群大小(popsize) = %d\n",popsize);
printf(" 染色体长度(lchrom) = %d\n",lchrom);
printf(" 最大进化代数(maxgen) = %d\n",maxgen);
printf(" 交叉概率(pcross) = %f\n", pcross);
printf(" 变异概率(pmutation) = %f\n", pmutation);
printf(" -------------------------------------------------\n");
skip(outfp,1);
fflush(outfp);//清除文件缓冲区,文件以写方式打开时将缓冲区内容写入文件
}
void generation()
{
int mate1, mate2, jcross, j = 0;
// 每代运算前进行预选
preselect();
// 选择, 交叉, 变异
do
{
// 挑选交叉配对
mate1 = select();
temp_mate1=mate1;
mate2 = select();
temp_mate2=mate2;
// 交叉,产生两个子代个体
jcross = crossover(oldpop[mate1].chrom, oldpop[mate2].chrom, newpop[j].chrom, newpop[j+1].chrom);
//变异
// 自适应变异概率
if(gen!=0)
{
if(newpop[j].fitness>=avg) //若新生个体适应度大于前一代平均适应度,则减小变异概率
pmutation = pm1-(pm1-pm2)*(max-newpop[j].fitness)/(max-avg);
else
pmutation = pm1; //否则变异概率不变
}
mutation(newpop[j].chrom);
if(gen!=0)
{
if(newpop[j+1].fitness>=avg)
pmutation = pm1-(pm1-pm2)*(max-newpop[j+1].fitness)/(max-avg);
else
pmutation = pm1;
}
mutation(newpop[j+1].chrom);
// 解码, 计算适应度
objfunc(&(newpop[j]));
//记录亲子关系和交叉位置
newpop[j].parent[0] = mate1+1;
newpop[j].xsite = jcross;
newpop[j].parent[1] = mate2+1;
objfunc(&(newpop[j+1]));
newpop[j+1].parent[0] = mate1+1;
newpop[j+1].xsite = jcross;
newpop[j+1].parent[1] = mate2+1;
j = j + 2;
}
while(j < (popsize-1));
}
void initmalloc() //为全局数据变量分配空间
{
unsigned nbytes;
int j;
// 分配给当前代和新一代种群内存空间
nbytes = popsize*sizeof(struct individual);
if((oldpop = (struct individual *) malloc(nbytes)) == NULL)
nomemory("oldpop");
if((newpop = (struct individual *) malloc(nbytes)) == NULL)
nomemory("newpop");
// 分配给染色体内存空间
nbytes = chromsize*sizeof(unsigned);
for(j = 0; j < popsize; j++)
{
if((oldpop[j].chrom = (unsigned *) malloc(nbytes)) == NULL)
nomemory("oldpop chromosomes");
if((newpop[j].chrom = (unsigned *) malloc(nbytes)) == NULL)
nomemory("newpop chromosomes");
}
if((bestfit.chrom = (unsigned *) malloc(nbytes)) == NULL)
nomemory("bestfit chromosome");
}
void freeall() // 释放内存空间
{
int i;
for(i = 0; i < popsize; i++)
{
free(oldpop[i].chrom);
free(newpop[i].chrom);
}
free(oldpop);
free(newpop);
free(bestfit.chrom);
}
void nomemory(char *string) // 内存不足,退出
{
printf("malloc: out of memory making %s!!\n",string);
exit(-1);
}
void report() // 输出种群统计结果
{
//void repchar(), skip();
//void writepop(), writestats();
repchar(outfp,"-",80);
skip(outfp,1);
if(printstrings == 1)
{
repchar(outfp," ",((80-17)/2));
printf("模拟计算统计报告 \n");
printf( "世代数 %3d", gen);
repchar(outfp," ",(80-28));
printf( "世代数 %3d\n", (gen+1));
printf("个体 染色体编码");
repchar(outfp," ",lchrom-5);
printf("适应度 父个体 交叉位置 ");
printf("染色体编码 ");
repchar(outfp," ",lchrom-5);
printf("适应度\n");
repchar(outfp,"-",80);
skip(outfp,1);
// writepop(outfp);
repchar(outfp,"-",80);
skip(outfp,1);
}
printf("第 %d 代统计: \n",gen);
printf("总交叉操作次数 = %d, 总变异操作数 = %d\n",ncross,nmutation);
printf(" 最小适应度:%f 最大适应度:%f 平均适应度 %f\n", min,max,avg);
printf(" 迄今发现最佳个体 => 所在代数: %d ", bestfit.generation);
printf(" 适应度:%f\n ", bestfit.fitness);
printf("染色体:");
writechrom((&bestfit)->chrom);
printf(" 对应的变量值: %f", bestfit.varible);
skip(outfp,1);
repchar(outfp,"-",80);
skip(outfp,1);
}
void writepop()//输出种群个体
{
struct individual *pind;
int j;
for(j=0; j<popsize; j++)
{
printf("%3d) ",j+1);
// 当前代个体
pind = &(oldpop[j]);
writechrom(pind->chrom);
printf(" %8f | ", pind->fitness);
// 新一代个体
pind = &(newpop[j]);
printf("(%2d,%2d) %2d ",pind->parent[0], pind->parent[1], pind->xsite);
writechrom(pind->chrom);
printf(" %8f\n", pind->fitness);
}
}
void writechrom(unsigned *chrom) // 输出染色体编码
{
int j, k, stop;
unsigned mask = 1, tmp;
for(k = 0; k < chromsize; k++)
{
tmp = chrom[k];
if(k == (chromsize-1))
stop = lchrom - (k*(8*sizeof(unsigned)));
else
stop =8*sizeof(unsigned);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -