遺傳算法(求函數極值)簡易代碼C語言200行

思路:

//目標函數:y=(x1-1)^2+(x2-2)^2;
#include<stdio.h>
#include<time.h>
#include<windows.h>
#define T 2000	//進化代數
#define N 200	//羣體個數
#define INT 8	//整數基因長度
#define FLOAT 20	//小數基因長度
#define MUTATE 0.005	//基因突變率

int t=0;	//代數計數
int gene[N][(INT+FLOAT)*2];	//基因
double value[N];	//函數值
double ratio[N];	//適應度概率區間
int pair[N];	//隨機配對規則
int totalRate=0;

void InitGroup();
double GetValue(int[],int);
int Mi(int,int);
void SortGroup();
void Output();
double Function(float,float);
void PairGroup();
void GeneMutate();
void Answer();

int main() {
	InitGroup();
	Output();
	while((t++)!=T) {
		GeneMutate();
		SortGroup();
		PairGroup();
	}
	SortGroup();
	Output();
	Answer();
}

//目標函數
double Function(double a,double b) {
	return -(a-1)*(a-1)-(b-2)*(b-2)+2;
}

//初始化種羣
void InitGroup() {
	for(int i=1; i<=N; i++) {
		totalRate+=i*i;
	}
	srand((unsigned)time(0));
	for(int i=0; i<N; i++) {
		for(int j=0; j<(INT+FLOAT)*2; j++) {
			gene[i][j]=rand()%2;
		}
	}
	for(int i=0; i<N; i++) {
		if(i==0) {
			ratio[i]=(i+1)*(i+1)/(double)totalRate;
		} else {
			ratio[i]=(i+1)*(i+1)/(double)totalRate;
			ratio[i]+=ratio[i-1];
		}
		//printf("%f\n",ratio[i]);
	}
	for(int i=0; i<N; i++) {
		value[i]=Function(GetValue(gene[i],1),GetValue(gene[i],2));
	}
}

//輸出種羣信息
void Output() {

	printf("個體基因:\n");
	for(int i=0; i<N; i++) {
		printf("【");
		for(int j=0; j<(INT+FLOAT)*2; j++) {
			if(j==INT) printf(",");
			else if(j==INT+FLOAT) printf("】,【");
			else if(j==INT*2+FLOAT) printf(",");
			printf("%d",gene[i][j]);
		}
		printf("】\n");
	}

	printf("個體數值:\n");
	for(int i=0; i<N; i++) {
		printf("%d: %f + %f -> %.16f\n",i,GetValue(gene[i],1),GetValue(gene[i],2),value[i]);
	}
}

//求a的b次方
int Mi(int a,int b) {
	int ans=1;
	for(int i=0; i<b; i++) {
		ans*=a;
	}
	return ans;
}

//求十進制值
double GetValue(int a[(INT+FLOAT)*2],int n) {
	int v=0;
	double ans;
	if(n==1) {
		for(int i=1; i<=INT+FLOAT; i++) {
			if(a[i-1]!=0) v+=Mi(2,INT+FLOAT-i);
		}
		ans=v/(double)Mi(2,FLOAT);
	} else if(n==2) {
		for(int i=1+INT+FLOAT; i<=(INT+FLOAT)*2; i++) {
			if(a[i-1]!=0) v+=Mi(2,(INT+FLOAT)*2-i);
		}
		ans=v/(double)Mi(2,FLOAT);
	}
	return ans;
}

//計算適應度並排序
void SortGroup() {
	for(int i=0; i<N; i++) {
		for(int j=0; j<N-1; j++) {
			if(value[j]>value[j+1]) {
				double b=value[j];
				value[j]=value[j+1];
				value[j+1]=b;
				for(int k=0; k<(INT+FLOAT)*2; k++) {
					int a=gene[j][k];
					gene[j][k]=gene[j+1][k];
					gene[j+1][k]=a;
				}
			}
		}
	}
}

//基因自由組合 
void PairGroup() {
	float b;
	//printf("\n配對規則:");
	for(int i=0; i<N; i++) {
		b=rand()/(RAND_MAX+1.0);
		for(int j=0; j<N; j++) {
			if(ratio[j]>=b) {
				pair[i]=j;
				//printf("%d  ",pair[i]);
				break;
			}
		}
	}
	//printf("\n分割位置:");
	int gene1[N][(INT+FLOAT)*2];
	for(int i=0; i<N-1; i+=2) {
		int pos=rand()%((INT+FLOAT)*2-1)+1;
		//printf("%d  ",pos);
		for(int k=0; k<(INT+FLOAT)*2; k++) {
			gene1[i][k]=gene[pair[i]][k];
			gene1[i+1][k]=gene[pair[i+1]][k];
		}
		for(int j=0; j<pos; j++) {
			int a=gene1[i][j];
			gene1[i][j]=gene1[i+1][j];
			gene1[i+1][j]=a;
		}
	}
	for(int i=0; i<N; i++) {
		for(int j=0; j<(INT+FLOAT)*2; j++) {
			gene[i][j]=gene1[i][j];
		}
	}
	for(int i=0; i<N; i++) {
		value[i]=Function(GetValue(gene[i],1),GetValue(gene[i],2));
	}
}

//基因突變 
void GeneMutate() {
	for(int i=0; i<N; i++) {
		for(int j=0; j<(INT+FLOAT)*2; j++) {
			if(rand()/(RAND_MAX+1.0)<MUTATE) {
				gene[i][j]=(gene[i][j]+1)%2;
			}
		}
	}
	for(int i=0; i<N; i++) {
		value[i]=Function(GetValue(gene[i],1),GetValue(gene[i],2));
	}
}

//輸出答案 
void Answer() {
	printf("\n\n最大值是:%.16f\n",value[N-1]);
	printf("此時,x1=%f, x2=%f\n",GetValue(gene[N-1],1),GetValue(gene[N-1],2));
}

運行結果:

 

 

 

發佈了89 篇原創文章 · 獲贊 195 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章