采用遗传算法求解函数最优值
一、实验要求
遗传算法(Genetic Algorithms,GA)是一种基于自然选择和自然遗传机制的搜索算法,它是一种有效的解决最优化问题的方法,属于一种进化算法。本实验要求采用简单遗传算法求解如下一元函数的最大值:
二、遗传算法基本流程
遗传算法由美国Michigan大学的John Holland和他的同事及学生提出的。类似于自然界演化的基本法则,“适者生存”是遗传算法的核心机制:复制(reproduce)、杂交(crossover)、变异(mutation)等自然界的生物演化规则在遗传算法中都得到类似的体现。遗传算法是从代表问题可能潜在解集的一个种群开始的。初代种群产生之后,按照适者生存、优胜劣汰的原理,逐代进化产生出越来越好的近似种群在每一代中,根据问题域中个体适应度大小挑选个体,并借助自然遗传学的遗传算子进行组合交叉和变异,产生出代表解的解集的种群。这个过程将导致种群像自然进化一样的后生代种群比前代更加适应于环境,末代种群中的最优个体经过解码可以作为问题近似最优解。
遗传算法的流程框图大体如下:
三、遗传算法求解详细过程
(1)编码
变量x作为实数,可以视为遗传算法的表现形式。从表现型到基因型的映射称为编码。二进制编码将某个变量值代表的个体表示为一个[0,1]二进制串(遗传算法最简单、最经典的编码方法)。若设定求解精确到6位小数,由于区间长度为2-(-1)=3,必须将区间[-1,2]分为3*10^6等份。因为2097152=2^21<3*10^6<=2^22=4194304,所以编码的二进制串长至少需要22位。
(2)产生初始种群
个体由串长为22的随机产生的二进制串组成染色体的基因码,产生一定数目的个体组成种群,种群的大小(规模)就是指种群中的个体数目。
(3)计算适应度
适应度大的个体其存活和被选中的概率大。适应度的计算就是对个体的计算,本例求函数最大值,目标函数值大的个体适应度大,所以直接引用目标函数作为适应度函数f(s)=f(x)。例如x1=0.637197通过编码得到的二进制串是s1=[1000101110110101000111],这个串就是个体。此个体的适应度就是:
假设选择种群数量为3 ,每个个体为s1=[1000101110110101000111],s2=[0000001110000000010000],s3=[1110000000111111000101],分别对应于数量值x1=0.637197,x2=-0.958973, x3=1.627888,另两个个体的适应度计算如下:
(4)选择
采用轮盘赌选择法,f(s1)=2.286345,f(s2)=1.078878,f(s3)=3.250650,把三个适应度依比例画在轮盘上,转动轮盘,最后停在哪里,就选择谁,适应度大的被选中概率大。
选择方法的实现:产生[0,1]间的随机数,以随机数落在那个范围进行选择:
[0,0.16),[0.16,0.51),[0.51,1]
(5)遗传操作
下面是经过选择操作后的两个个体:
s2=[00000 01110000000010000] ,
s3=[11100 00000111111000101],
首先执行单点交叉,随机随机选择交叉点,将之后的串交叉,得到新的两个个体为:
s2'=[00000 00000111111000101]
s3'=[11100 01110000000010000]
这两个个体的适应度分别为:
(6)变异操作
假定以一小概率选择S3的第5个遗传因子(第5位)变异,遗传因子由原来的0变为1,产生新个体:s3'=[1110100000111111000101],该个体适应度为:
个体的适应度比它的父个体的适应度减小了。
但如果选中第11个遗传因子变异,产生新个体为s3''= [11100000001111111000101],适应度,又发现s3''的适应度比其父个体的适应度改善了,这说明变异操作的“扰动”作用(全局搜索)。
CODE:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
//import java.util.Scanner;
public class GA {
static int geneLength = 22;
static int individualSize = 16;
static int maxEvolve = 50;
static double crossoverProbability = 0.7;
static double mutationProbablility = 0.2;
static double sumFitness = 0.0;
static class individual implements Cloneable{
double fitness;
double Pl;
double Pr;
int[] gene;
public individual(double fitness, double pl, double pr, int[] gene) {
super();
this.fitness = fitness;
Pl = pl;
Pr = pr;
this.gene = gene;
}
@Override
public String toString() {
return "individual [fitness=" + fitness + ", Pl=" + Pl + ", Pr=" + Pr + ", gene=" + Arrays.toString(gene)
+ "]";
}
public Object clone(){
individual idd = null;
try {
idd = (individual) super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
idd.gene = this.gene.clone();
return idd;
}
}
static List<individual> initPop(){
List<individual> population = new ArrayList<individual>();
int ca = 0;
while(ca < individualSize){
int[] gene = new int[geneLength];
for(int i=0; i<geneLength; i++){
gene[i] = (int)(Math.random()*100)%2;
}
population.add(new individual(0.0, 0.0, 0.0, gene));
ca++;
}
return population;
}
static void updateFitness(List<individual> population){
int constant = 4194103;
for(int i=0; i<individualSize; i++){
StringBuffer sb = new StringBuffer();
for(int j=0; j<geneLength; j++){
sb.append(population.get(i).gene[j]);
}
int H = Integer.valueOf(sb.toString(), 2);
double x = -1.0 + 3.0*(H*1.0/constant*1.0);
population.get(i).fitness = x*Math.sin(10*Math.PI*x)+2.0;
sumFitness += population.get(i).fitness;
}
}
static individual bestIndividual(List<individual> population){
individual best = (individual) population.get(0).clone();
for(int i=1; i<individualSize; i++){
if(population.get(i).fitness > best.fitness){
best = (individual) population.get(i).clone();
}
}
return best;
}
static List<individual> selectPop(List<individual> population){
int ca = 0;
List<individual> newPopulation = new ArrayList<individual>();
double start = 0.0;
for(int i=0; i<individualSize; i++){
double p = population.get(i).fitness/sumFitness;
population.get(i).Pl = start;
population.get(i).Pr = p + start;
start = population.get(i).Pr;
}
while(ca < individualSize){
boolean flag = false;
double P = Math.random();
for(int j=0; j<individualSize; j++){
if(P>population.get(j).Pl && P<population.get(j).Pr){
newPopulation.add(population.get(j));
flag = true;
break;
}
}
if(!flag){
newPopulation.add(bestIndividual(population));
}
ca++;
}
return newPopulation;
}
static void crossover(List<individual> population){
boolean flag = false;
int father = 0;
int mother = 0;
for(int i=0; i<individualSize; i++){
double P = Math.random();
if(P < crossoverProbability){
if(flag){
mother = i;
int l = (int) (Math.random()*geneLength);
int r = (int) (Math.random()*geneLength);
if(l>r){
int t = l;
l = r;
r = t;
}
int t[] = new int[geneLength];
for(int f=l; f<r; f++){
t[f] = population.get(father).gene[f];
population.get(father).gene[f] = population.get(mother).gene[f];
population.get(mother).gene[f] = t[f];
}
flag = false;
}
else{
father = i;
flag = true;
}
}
}
}
static void mutation(List<individual> population){
for(int i=0; i<individualSize; i++){
double p = Math.random();
if(p<mutationProbablility){
int cnt = (int) (Math.random()*geneLength);
while(cnt>0){
int point = (int) (Math.random()*(geneLength-1));
population.get(i).gene[point] = 1-population.get(i).gene[point];
cnt -= 1;
}
}
}
for(int i=0; i<geneLength; i++){
int count = 0;
for(int j=0; j<individualSize; j++){
count += population.get(j).gene[i];
}
if(count<3 || count>(individualSize-3)){
int cn = (int) (Math.random()*individualSize);
population.get(cn).gene[i] = 1-population.get(cn).gene[i];
int cn1 = (int) (Math.random()*individualSize);
while(cn1==cn){
cn1 = (int) (Math.random()*individualSize);
}
population.get(cn1).gene[i] = 1-population.get(cn1).gene[i];
}
}
}
public static void main(String[] args) {
// Scanner in = new Scanner(System.in);
int ca = 0;
List<individual> population = initPop();
updateFitness(population);
List<individual> bestList = new ArrayList<individual>();
while(ca < maxEvolve){
List<individual> newP = selectPop(population);
crossover(newP);
mutation(newP);
population = newP;
updateFitness(population);
bestList.add(bestIndividual(population));
ca++;
System.out.println();
for(int i=0; i<individualSize; i++){
System.out.print("基因:"+Arrays.toString(population.get(i).gene)+" ");
System.out.println("函数值:"+population.get(i).fitness);
}
}
System.out.println("---------------结果---------------");
individual P = bestIndividual(population);
System.out.print("基因:"+Arrays.toString(P.gene)+" ");
System.out.println("函数值:"+P.fitness);
}
}
输出:
问题函数图像:
算法进化图像: