?? gaopt.c
字號:
/**************************************************************/
/* 基于基本遺傳算法的函數(shù)最優(yōu)化 */
/* 同濟大學計算機系 王小平 2000年5月 */
/**************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<graphics.h>
#include<math.h>
#include<time.h>
#include<string.h>
#include "graph.c"
#include "operator.c"
#define POP_SIZE 25 /* 種群大小 */
#define G_LENGTH 8 /* 染色體長度 */
#define C_RATE 0.2 /* 交叉概率 */
#define M_RATE 0.01 /* 變異概率 */
#define XMAX 255 /* 函數(shù)變量最大值 */
#define X1 350 /* 函數(shù)圖形區(qū)窗口左上點X坐標 */
#define Y1 40 /* 函數(shù)圖形區(qū)窗口左上點Y坐標 */
#define XR1 255 /* 函數(shù)圖形區(qū)窗口長度 */
#define YR1 200 /* 函數(shù)圖形區(qū)窗口高度 */
#define X2 360 /* 適應度圖形區(qū)窗口左上點X坐標 */
#define Y2 280 /* 適應度圖形區(qū)窗口左上點Y坐標 */
#define XR2 250 /* 適應度圖形區(qū)窗口長度 */
#define YR2 100 /* 適應度圖形區(qū)窗口寬度 */
#define STEP 2 /* 適應度圖形區(qū)X方向步長 */
void initialize_gene(gene,pop_size,g_length)
/* 種群中個體遺傳基因型的初始化 */
unsigned char *gene; /* 遺傳基因 */
int pop_size; /* 種群大小 */
int g_length; /* 個體染色體長度 */
{
int i,j;
randomize();
for(i=0;i<pop_size;i++)
for(j=0;j<g_length;j++)
*(gene+i*g_length+j)=random(2);
}
int gene_to_pheno(gene,g_length)
/* 基因型到表現(xiàn)型的變換--解碼 */
unsigned char *gene; /* 基因型 */
int g_length; /* 染色體長度 */
{
int i,pheno;
pheno=0;
for(i=0;i<g_length;i++)
pheno=pheno*2+*(gene+i);
return(pheno);
}
void calc_fitness(gene,fitness,pop_size,g_length,func, max_fit,avg_fit)
/* 計算種群中個體的適應度 */
unsigned char *gene; /* 個體的遺傳基因 */
double *fitness; /* 個體的適應度 */
double *func; /* 評價函數(shù) */
double *max_fit,*avg_fit; /* 最大適應度與平均適應度 */
int pop_size; /* 種群大小 */
int g_length; /* 個體染色體長度 */
{
unsigned char *g; /* 個體的遺傳基因指針變量 */
int pheno; /* 個體的表現(xiàn)型 */
int i,j;
double f;
*max_fit=0.0;
*avg_fit=0.0;
f=(double)pop_size;
for(i=0;i<pop_size;i++)
{
g=gene+i*g_length;
pheno=gene_to_pheno(g,g_length);
*(fitness+i)=*(func+pheno);
if(*(fitness+i)>*max_fit)
*max_fit=*(fitness+i);
*avg_fit=*avg_fit+*(fitness+i)/f;
}
}
void sga_reproduction(gene,fitness,new_gene,new_fitness,pop_size,g_length)
/* 基于個體的適應度評價進行新一代個體的選擇(輪盤賭方法),選擇后分別將新的基因型和適應度代入到新個體中 */
unsigned char *gene; /* 當前代的個體遺傳基因型 */
unsigned char *new_gene; /* 新一代的個體遺傳基因型 */
double *fitness; /* 當前代的個體適應度 */
double *new_fitness; /* 新一代的個體適應度 */
int pop_size; /* 種群大小 */
int g_length; /* 染色體長度 */
{
double sum_of_fitness;
double border;
double r; /* 輪盤上的選擇位置變量 */
int i,j;
int num;
sum_of_fitness=0.0;
for(i=0;i<pop_size;i++) /* 輪盤賭的選擇循環(huán) */
sum_of_fitness=sum_of_fitness+*(fitness+i);
for(i=0;i<pop_size;i++)
{
r=sum_of_fitness*(random(10001)/10000.0);
num=0;
border=*fitness;
while(border<r)
{
num++;
border=border+*(fitness+num);
}
for(j=0;j<g_length;j++)
*(new_gene+i*g_length+j)=*(gene+num*g_length+j);
*(new_fitness+i)=*(fitness+num);
}
}
void sga_crossover(gene,pop_size,g_length,c_rate)
/* 基本遺傳算法的交叉操作--單點交叉 */
unsigned char *gene; /* 遺傳基因 */
int pop_size; /* 種群大小 */
int g_length; /* 個體染色體長度 */
double c_rate; /* 交叉概率 */
{
unsigned char *gene1; /* 父個體1的遺傳基因指針變量 */
unsigned char *gene2; /* 父個體1的遺傳基因指針變量 */
unsigned char work; /* 中間變量 */
int i,j;
int c_pos; /* 交叉位置變量 */
double r; /* 隨機數(shù)變量 */
for(i=0;i<pop_size-1;i=i+2)
{
r=random(10001)/10000.0;
if(r<=c_rate)
{
gene1=gene+g_length*i;
gene2=gene1+g_length;
c_pos=random(g_length-2)+1;
for(j=c_pos;j<g_length;j++) /* 兩個父個體之間部分遺傳基因的交換 */
{ work=*(gene1+j);
*(gene1+j)=*(gene2+j);
*(gene2+j)=work;
}
}
}
}
void sga_mutation(gene,pop_size,g_length,m_rate)
/* 基本遺傳算法的變異操作--個體遺傳基因按小概率翻轉 */
unsigned char *gene; /* 遺傳基因 */
int pop_size; /* 種群大小 */
int g_length; /* 染色體長度 */
double m_rate; /* 變異概率 */
{
int i,j;
double r;
for(i=0;i<pop_size;i++)
{
for(j=0;j<g_length;j++)
r=random(10001)/10000.0;
if(r<=m_rate) /* 變異發(fā)生判斷 */
{
if ( *(gene+g_length*i+j)==0)
*(gene+g_length*i+j)=1;
else
*(gene+g_length*i+j)=0;
}
}
}
void make_function(func,xmax)
/* 生成一個函數(shù), 用于最優(yōu)化計算的目標函數(shù)(最大化) */
/* f=∑ai*sin(x* bi+ci) 其中 ai∈[0, 0.35]的均勻隨機數(shù)
bi∈[2*pi, 5*2*pi] /xmax的均勻隨機數(shù)
ci∈[0, 2*pi]的均勻隨機數(shù)
x∈[0,xmax]為優(yōu)化變量
i=1,2,3 */
double *func; /* 函數(shù)值 */
int xmax; /* 變量最大值 <XMAX */
{
int x,i;
double a[3],b[3],c[3];
double pi=3.141592;
double fxmax,fx,f_value;
double f_min,f_max,f_mid,f_range;
double dbl;
randomize();
fxmax=(double)xmax;
for(i=0;i<3;i++) /* 優(yōu)化函數(shù)為三個三角函數(shù)之和 */
{
a[i]=0.35*(random(10001)/10000.0);
b[i]=(4*(random(10001)/10000.0)+1)*2.0*pi/fxmax;
c[i]=2.0*pi*(random(10001)/10000.0);
}
f_min=1.0;
f_max=0.0;
for(x=0;x<=xmax;x++) /* 將優(yōu)化函數(shù)正規(guī)化為[0,1]區(qū)間數(shù) */
{
fx=(double)x;
f_value=0.0;
for(i=0;i<3;i++)
{
dbl=b[i]*fx+c[i];
f_value=f_value+a[i]*sin(dbl);
}
f_value=f_value+0.5;
if(f_value>f_max) f_max=f_value;
if(f_value<f_min) f_min=f_value;
*(func+x)=(double)f_value;
}
f_range=f_max-f_min;
f_mid=(f_max+f_min)/2.0;
for(x=0;x<=xmax;x++)
{
f_value=(*(func+x)-f_mid)/f_range+0.5;
if(f_value>1.0) f_value=1.0;
else if(f_value<0.0) f_value=0.0;
*(func+x)=f_value;
}
}
void g_draw_func(func,xmax)
/* 繪制優(yōu)化函數(shù)的圖形 */
double *func; /* 函數(shù)值 */
int xmax; /* 變量最大值 */
{
int x,y,x_old,y_old,i;
double f;
g_rectangle(X1+1,Y1+1,X1+XR1-1,Y1+YR1-1,0,1);
g_rectangle(X1+1,Y1-12,X1+XR1,Y1-1,8,1);
g_rectangle(X1,Y1,X1+XR1,Y1+YR1,6,0);
x_old=X1;
y_old=Y1+YR1-(int)(*func*YR1);
f=XR1/(double)xmax;
for(i=1;i<=xmax;i++)
{
x=X1+(int)(i*f);
y=Y1+YR1-(int)(*(func+i)*YR1);
g_line(x_old,y_old,x,y,12);
x_old=x;
y_old=y;
}
}
void g_init_grph(func,xmax)
/* 初始化畫面的圖形 */
double *func; /* 函數(shù)值 */
int xmax; /* 變量最大值 */
{
int x,y,x_old,y_old,i;
char c[5];
/*初始化函數(shù)圖形區(qū)*/
g_rectangle(320,0,639,399,8,1);
g_rectangle(321,1,638,16,8,1);
disp_hz16("基于基本遺傳算法的函數(shù)最優(yōu)化",370,1,15);
disp_hz16("g(x)",X1-30,Y1-18,15);
disp_hz16("1.0",X1-30,Y1,15);
disp_hz16("0",X1-10,Y1+YR1,15);
disp_hz16("x",X1+XR1+10,Y1+YR1-20,15);
disp_hz16("XMAX",X1+XR1-10,Y1+YR1,15);
g_draw_func(func,xmax);
/* 初始化適應度圖形區(qū) */
g_rectangle(X2,Y2,X2+XR2,Y2+YR2,0,1);
g_rectangle(X2,Y2,X2+XR2,Y2+YR2,6,0);
setcolor(15);
disp_hz16("最大適應度",X2+5,Y2-18,15);
g_line(X2+90,Y2-10,X2+110,Y2-10,11);
setcolor(15);
disp_hz16("平均適應度",X2+120,Y2-18,15);
g_line(X2+205,Y2-10,X2+225,Y2-10,9);
setcolor(15);
disp_hz16("世代數(shù)",X2+168,Y2+YR2+10,15);
g_text(X2-30,Y2,15,"1.0");
/* g_text(X2-30,Y2+YR2,15,"0.0");*/
}
void g_plot_grph(num,gene,fitness,pop_size,g_length,func, xmax,max_fit,m_f_old,avg_fit,a_f_old,gen_num)
/* 隨世代進化更新圖形 */
unsigned char *gene; /* 遺傳基因 */
double *fitness; /* 適應度 */
double *func; /* 函數(shù)值 */
double max_fit,m_f_old; /* 當前代最大適應度,上一代最大適應度 */
double avg_fit,a_f_old; /* 當前代平均適應度,上一代平均適應度 */
int num; /* 當前世代數(shù) */
int pop_size; /* 種群大小 */
int g_length; /* 染色體長度 */
int xmax; /* 變量最大值 */
int gen_num; /* 最大世代數(shù) */
{
int i,j,x,y,x_old,y_old;
double f;
unsigned char *g;
char c[10];
/* 顯示當前世代種群中個體的遺傳基因 */
if(num==gen_num-1)
{
for(i=0;i<pop_size;i++)
{
printf("Indv.%2d:",i+1);
for(j=0;j<g_length;j++)
printf("%d",*(gene+i*g_length+j));
printf("==>Fitness %.4f\n",*(fitness+i));
}
printf("Max_fit=%f \n",max_fit);
printf("Avg_fit=%f \n",avg_fit);
}
/* 顯示個體在函數(shù)圖形區(qū)中的位置 */
g_draw_func(func,xmax);
f=XR1/(double)xmax;
for(i=0;i<pop_size;i++)
{
g=gene+i*g_length;
j=gene_to_pheno(g,g_length);
x=X1+(int)(j*f);
y=Y1+YR1-*(func+j)*YR1;
g_line(x,y-10,x,y,15);
}
/* 適應度曲線的更新 */
if(num!=1 && num<=XR2/STEP)
{
if(num%10==0) /* 每隔10代更新一次 */
{
x=X2+(num-1)*STEP;
g_line(x,Y2+1,x,Y2+YR2-1,1);
sprintf(c,"%d",num);
if(num<100 || num%20==0)
g_text(x-8,Y2+YR2,15,c);
}
x_old=X2+(num-1)*STEP;
x=x_old+STEP;
y_old=Y2+YR2-(int)(m_f_old*YR2);
y=Y2+YR2-(int)(max_fit*YR2);
g_line(x_old,y_old,x,y,11);
y_old=Y2+YR2-(int)(a_f_old*YR2);
y=Y2+YR2-(int)(avg_fit*YR2);
g_line(x_old,y_old,x,y,9);
}
}
void generation(gene,fitness,pop_size,g_length, c_rate,m_rate,new_gene,new_fitness,func,xmax)
/* 世代進化的模擬 */
unsigned char *gene; /* 當前世代的個體遺傳基因型 */
unsigned char *new_gene; /* 新一代的個體遺傳基因型 */
double *fitness; /* 當前世代的個體適應度 */
double *new_fitness; /* 新一代的個體適應度 */
double *func; /* 優(yōu)化函數(shù) */
double c_rate,m_rate; /* 交叉概率和變異概率 */
int pop_size, g_length; /* 種群大小與染色體長度 */
{ int gen_max; /* 最大模擬世代數(shù) */
int i,j,k;
double max_fit,avg_fit; /* 當前代最大適應度和平均適應度 */
double m_f_old,a_f_old; /* 新一代最大適應度和平均適應度 */
char choice[3];
setcolor(15);
disp_hz16("輸入最大模擬世代數(shù):",10,1,20);
gscanf(170,1,4,0,3,"%s",choice);
gen_max=atoi(choice);
m_f_old=0.0;
a_f_old=0.0;
for(i=0;i<gen_max;i++)
{
if(i==gen_max-1)
{
printf("\n");
printf("************Gen.%d*************\n",i+1);
}
calc_fitness(gene,fitness,pop_size,g_length,func,
&max_fit,&avg_fit);
sga_reproduction(gene,fitness,new_gene,new_fitness,
pop_size,g_length);
for(j=0;j<pop_size;j++)
{
*(fitness+j)=*(new_fitness+j);
for(k=0;k<g_length;k++)
*(gene+g_length*j+k)=*(new_gene+g_length*j+k);
}
sga_crossover(gene,pop_size,g_length,c_rate);
sga_mutation(gene,pop_size,g_length,m_rate);
g_plot_grph(i,gene,fitness,pop_size,g_length,func,
xmax,max_fit,m_f_old,avg_fit,a_f_old,gen_max);
m_f_old=max_fit;
a_f_old=avg_fit;
}
}
main() /* 主程序 */
{
/*當前代的個體遺傳基因型與新一代的個體遺傳基因型 */
unsigned char gene[POP_SIZE][G_LENGTH], new_gene[POP_SIZE][G_LENGTH];
/*當前代的個體適應度與新一代個體的適應度 */
double fitness[POP_SIZE], new_fitness[POP_SIZE];
/* 優(yōu)化函數(shù) */
double func[XMAX+1];
/* 初始化圖形設置 */
g_init();
/* 生成優(yōu)化函數(shù) */
make_function(func,XMAX);
/* 初始化顯示畫面 */
g_init_grph(func,XMAX);
/* 初始化種群 */
initialize_gene(gene,POP_SIZE,G_LENGTH);
/* 世代進化模擬 */
generation(gene,fitness,POP_SIZE,G_LENGTH,
C_RATE,M_RATE,new_gene,new_fitness,func,XMAX);
setcolor(9);
disp_hz16("回車鍵結束",350,430,20);
getch();
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -