遗传算法的基础知识与编程

本文介绍了遗传算法的基础知识,包括其模拟生物进化的过程和主要概念,如染色体、适应值、评估函数、选择、交配和变异算子。遗传算法的执行步骤包括染色体编码、群体初始化、适应值评估、选择、交配和变异。文章还提到了在编程实现中,遗传算法用于解决0-1背包问题,并给出了代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第五篇为《遗传算法的基础知识与编程》

一、遗传算法基础知识

借鉴自然进化的理念,优化问题的过程可以看成类似于生物进化的过程,通过模拟自然界的生物进化,遗传算法被提出用于解决优化问题。

遗传算法吸收了生命科学与工程科学的重要理论成果,用于解决复杂优化问题。

自然进化过程如下图1所示,其主要包括自然选择,交配、变异以及淘汰了这些过程,遗传算法结合自然进化的方式的方式来解决优化问题。

                                                    

                                                                                  图1 自然进化过程

在生物的进化与遗传过程中有一个重要的携带信息的结构,即染色体。染色体是遗传信息基因的载体,基因在染色体上按照一定的次序组合。

在遗传算法中,问题的每个有效解也被称为一个“染色体”,染色体的具体形式是一个使用特定编码方式生成的编码串。编码串中的每一个编码单元称为“基因”。

在遗传算法中海油以下基本概念:

(1)适应值:适应值用于区分染色体的优劣,适应值越大的染色体越优秀。

(2)评估函数:用来计算并确定染色体对应的适应值

(3)选择算子:按照一定的规则对群体的染色体进行选择,得到父代种群。越优秀的染色体被选中的次数越多。

(4)交配算子:作用于没两个成功交配的染色体,染色体交换各自的部分基因,产生两个子染色体。子染色体取代父染色体进入新种群,而没有交配的染色体则直接进入新种群。

(5)变异算子:使新种群进行小概率的变异。

二、遗传算法执行步骤

(一)进一步概念

1、染色体编码

在使用遗传算法的时候,首先需要把要解决的问题的解表示出来,即染色体的编码方式。只有先确定了编码方式,才能进行接下类的交配变异等操作。

目前常用的比较简单的编码方式有:

(1)二进制编码方法:编码的染色体是一个二进制符号序列,在下面的程序编程中使用的编码方法就是二进制编码方法。在二进制编码方法中,染色体上的每个基因智能取0和1,就是对应着下面0-1背包的0和1.

(2)浮点数编码方式:浮点数编码方法中,染色体的长度等于问题定义的解的变量个数,染色体的每一个基因等于解的每一维变量。

2、群体初始化

遗传算法在开始进化迭代之前需要初始化进化的群体,一般采用产生随机数的方法进行群体的初始化。比如下面的编程就使用随机数初始这个染色体,因为染色体上只有0与1,因此只需根据随机数来生成0与1即可。

3、评估适应值

对于适应值的评估使用评估函数来进行,适应度用来评估一个染色体的优劣。评估函数基本是根据问题的优化目标来进行确定的。在遗传算法中,规定适应值越大的染色体越好。

4、选择算子

种群的选择操作使用轮盘赌选择算法,轮盘赌选择算法基于概率的随机选择,比如电影里经常看到的在枪里放一颗子弹,进行开枪赌运气。

5、交配算子

在染色体交配阶段,每个染色体能否进行交配由交配概率P来决定,如果随机数在这个概率之内则表示两个染色体需要进行交配。

6、变异算子

同样的有一个变异算子,设定一个变异概率P,产生随机数小于这个编译概率,那么可以进行变异。

(二)遗传算法步骤

Step 1 :初始化群体N,使用随机数生成器对群体中的每个个体染色体进行随机编码,标记迭代次数c=0。

Step 2:使用评估函数对这些初始出的个体染色体进行评估,计算出他们的适应度,然后标记最大的适应值Best。

Step 3:采用轮盘赌方式进行选择操作,产生规模同样为N的种群

Step 4:按照交配概率P,选择则染色体进行交配。

Step 5:按照变异概率P,选择染色体进行变异。

Step 6:使用交配变异后的新种群代替旧种群,重新通过评估函数计算适应值。若新种群的最大适应值在于前面标记的Best,就更新Best。

Step 7:将迭代次数加1,继续第三步进行迭代。

三、遗传算法编程

代码好像不是自己写的,来自网络,三年前找到的代码,找不到出处了,侵删。

该代码为遗传算法解决0-1背包问题,主要包含如下两个文件:

(1)ga.c:

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <time.h>
#include <string.h>

#define ROUND 4000
#define INIT 100					//初始染色体数目
#define TotalGoods 50	            //货物总数
#define Load       600		        //背包总容量   
int Weights[TotalGoods];            //存储每件货物重量数组    
int Values[TotalGoods];             //存储每件货物价值数组
int TotalWeights[INIT];             //存储每个组合的总重量
int TotalValues[INIT];              //存储每个组合的总价值
double Fitness[INIT];               //适应度

char ParentChromosome[INIT][TotalGoods+1];  //存储父代基因组合,即染色体
char ChildChromosome[INIT][TotalGoods+1];   //存储子代基因组合,即染色体
double Prob[INIT];							//每个组合的选择概率,用于轮盘赌选择
int count = 0;

/*******************************************************/
//读取配置文件             
//Line1:    货物重量
//Line2:    货物价值
//Line3……:备选初始组合,因为初始组合是随机产生的,不能保证满足“重量和<背包容量”,须在本程序中进行判断
/******************************************************/

void ReadConfFIle(char *filename)
{
	int i, j;
	int sum=0;
	char *fname = filename;
	FILE *fid = fopen(fname, "r");
	for (i=0; i< TotalGoods; i++)
	{
		fscanf(fid, "%d",&Weights[i]);
	}
	for (i=0; i< TotalGoods; i++)
	{
		fscanf(fid, "%d", &Values[i]);
	}
	//从文件中读取满足约束条件的组合作为初始组合
	for (i=0; i< INIT; i++)
	{
		fscanf(fid, "%s", &ParentChromosome[i]);
		sum=0;
		for (j=0; j< TotalGoods; j++)
		{
			sum += (int)(ParentChromosome[i][j]-48) * Weights[j];
		}
		if(sum >= Load)
		{
			i--;
		}
		
	}
	fclose(fid);

}
/*******************************************/
//计算所有个体的适应度
//得到适应度数组
//输入:
//	  char Chromosome[][]: 父辈基因的组合
//输出:
//    double *fitness    : 所有基因组合的适应度
/******************************************/

void CalculateFitness(char  Chromosome[][TotalGoods+1],double *fitness )
{
	int i,j;
	
	for (i=0; i< INIT; i++)
	{
		TotalValues[i] = 0;
		TotalWeights[i]=0;
		for (j=0; j< TotalGoods; j++)
		{
			TotalWeights[i]+=Weights[j]*(int)(Chromosome[i][j]-48);
			TotalValues[i] +=Values[j] *(int)(Chromosome[i][j]-48);
		}
		
		fitness[i]=(double)TotalValues[i];

	}

}
/********************************************************/
//通过轮盘赌来选择确定选择交叉的父染色体
//parent中存储了两个选择的父染色体的下标
//输入:
//     double *fitness: 适应度,即每一个组合的价值
//     double *prob   : 每个组合的选择概率
//输出:
//     int *parent    : 选择出来的两个父染色体的标号
/*************************************
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值