深入理解Java遗传算法的设计思路

478 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第16天,点击查看活动详情

深入理解Java遗传算法

这篇文章主要为大家详细介绍了Java遗传算法,本文对基因的编码采用二进制规则,分享了对Java遗传算法的理解,感兴趣的小伙伴们可以参考一下

关于遗传算法的详细原理以及具体的定义这里就不多介绍,想了解的可以自行百度,下面就简单介绍下自己对遗传算法的理解,本文对基因的编码采用二进制规则。

算法思想: 

遗传算法参照达尔文的进化论,认为物种都是向好的方向去发展(适者生存),因此可以认为到足够的代数之后,得到的最值可实际的最值很接近。

算法步骤:

  • 1)随机产生一个种群;
  • 2)计算种群的适应度、最好适应度、最差适应度、平均适应度等指标;
  • 3)验证种群代数是否达到自己设置的阈值,如果达到结束计算,否则继续下一步计算;
  • 4)采用转盘赌法选择可以产生下一代的父代,产生下一代种群(种群中个体数量不变);
  • 5)种群发生基因突变;
  • 6)重复2、3、4、5步。

算法实现-基因部分

1、种群个体(这里认为是染色体),在个体中,我们为这个个体添加两个属性,个体的基因和基因对应的适应度(函数值)。

public class Chromosome { 
  private boolean[] gene;//基因序列 
  private double score;//对应的函数得分 
} 

2、随机生成基因序列,基因的每一个位置是0还是1,这里采用完全随机的方式实现。

public Chromosome(int size) { 
  if (size <= 0) { 
    return; 
  } 
  initGeneSize(size); 
  for (int i = 0; i < size; i++) { 
    gene[i] = Math.random() >= 0.5; 
  } 
} 
 
private void initGeneSize(int size) { 
  if (size <= 0) { 
    return; 
  } 
  gene = new boolean[size]; 
} 

3、把基因转化为对应的值,比如101对应的数字是5,这里采用位运算来实现。

public int getNum() { 
  if (gene == null) { 
    return 0; 
  } 
  int num = 0; 
  for (boolean bool : gene) { 
    num <<= 1; 
    if (bool) { 
      num += 1; 
    } 
  } 
  return num; 
} 

4、基因发生变异,对于变异的位置这里完全采取随机的方式实现,变异原则是由1变为0,0变为1。

public void mutation(int num) { 
  //允许变异 
  int size = gene.length; 
  for (int i = 0; i < num; i++) { 
    //寻找变异位置 
    int at = ((int) (Math.random() * size)) % size; 
    //变异后的值 
    boolean bool = !gene[at]; 
    gene[at] = bool; 
  } 
} 

5、克隆基因,用于产生下一代,这一步就是将已存在的基因copy一份。

public static Chromosome clone(final Chromosome c) { 
  if (c == null || c.gene == null) { 
    return null; 
  } 
  Chromosome copy = new Chromosome(); 
  copy.initGeneSize(c.gene.length); 
  for (int i = 0; i < c.gene.length; i++) { 
    copy.gene[i] = c.gene[i]; 
  } 
  return copy; 
} 

6、父母双方产生下一代,这里两个个体产生两个个体子代,具体哪段基因差生交叉,完全随机。

public static List<Chromosome> genetic(Chromosome p1, Chromosome p2) { 
  if (p1 == null || p2 == null) { //染色体有一个为空,不产生下一代 
    return null; 
  } 
  if (p1.gene == null || p2.gene == null) { //染色体有一个没有基因序列,不产生下一代 
    return null; 
  } 
  if (p1.gene.length != p2.gene.length) { //染色体基因序列长度不同,不产生下一代 
    return null; 
  } 
  Chromosome c1 = clone(p1); 
  Chromosome c2 = clone(p2); 
  //随机产生交叉互换位置 
  int size = c1.gene.length; 
  int a = ((int) (Math.random() * size)) % size; 
  int b = ((int) (Math.random() * size)) % size; 
  int min = a > b ? b : a; 
  int max = a > b ? a : b; 
  //对位置上的基因进行交叉互换 
  for (int i = min; i <= max; i++) { 
    boolean t = c1.gene[i]; 
    c1.gene[i] = c2.gene[i]; 
    c2.gene[i] = t; 
  } 
  List<Chromosome> list = new ArrayList<Chromosome>(); 
  list.add(c1); 
  list.add(c2); 
  return list; 
}