本篇并非介绍如何从0开始开发遗传算法框架,反而推荐各位使用已有的GA库jenetics来做遗传算法。

GA算法的逻辑还是贴下:

好了,下面介绍的是基于jenetics开发的更贴近业务侧的框架,以及使用方法。

pom依赖,毕竟java的嘛,就不要用matlab、R、python这些了

<!-- https://mvnrepository.com/artifact/io.jenetics/jenetics -->
<dependency>
<groupId>io.jenetics</groupId>
<artifactId>jenetics</artifactId>
<version>5.1.0</version>
</dependency>
<dependency>
<groupId>io.jenetics</groupId>
<artifactId>jenetics.ext</artifactId>
<version>5.1.0</version>
</dependency>

先看看我们提供的这个框架,能怎样简化业务侧代码吧:

public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(5); //需要指定一个线程池,因为GA算法需要很多运算 Demo1SolutionConverter demo1SolutionConverter = new Demo1SolutionConverter(); //这个class中定义了GA算法所需的底层基因序列的定义、以及业务解决方案class与基因的互相转换逻辑
Demo1FitnessBuilder fitnessBuilder = new Demo1FitnessBuilder(); //这个class定义了适应度函数的指向(遗传算法非常依赖适应度函数,非常非常依赖,重中之重) EngineInvokeOptions options = new EngineInvokeOptions(); //引擎调用默认参数,如需改写默认参数单独修改即可
options.setFitnessBuilder(fitnessBuilder);
options.setEnableMaxLimits(true); //设置为停止条件为最大种群次数限制
options.setMaxLimits(20); //设置为最大次数限制为20次,既:20次种群迭代 for(int idx=0;idx<20;idx++) { //连续执行20次看效果
MinMaxScaler minMaxScaler = new MinMaxScaler(100, false); GAEngine gaEngine = new GAEngine(50, executorService); Demo1SolutionConverter.Demo1Solution solution = (Demo1SolutionConverter.Demo1Solution) gaEngine.generate(demo1SolutionConverter, minMaxScaler, options);
System.out.println(solution.toString());
} executorService.shutdown();
}  

我们先看看核心class:Demo1SolutionConverter,这个是每个业务都不同的地方,需要单独业务单独编码

public class Demo1SolutionConverter extends DefaultSolutionConverter {                                         //DefaultSolutionConverter是框架里的默认实现,已经实现了很多默认方法
@Override
public AbstractSolution convert2Solution(EvolvingSolutionInfo solutionInfo) {
Demo1Solution solution=new Demo1Solution();
solution.setFitnessValues(solutionInfo.getFitnessValues()); Genotype<IntegerGene> geneMap=solutionInfo.getMap(); //这个是获取基因架 Chromosome<IntegerGene> chromosome=geneMap.getChromosome(); //获取默认的也就是第一个基因条 for(int idx=0;idx<chromosome.length();idx++) //开始业务解码
{
IntegerGene integerGene=chromosome.getGene(idx);
if(integerGene.intValue()==1)
{
solution.getSelectedIds().add(idx); //这里实现的解码逻辑:共10个数字,有2种可能0和1,0代表不选中,1代表选中,选中了就会加入selectedIds这个List里
}
} return solution;
} @Override
public Genotype<IntegerGene> loadGenotype() { //这个是唯一一个DefaultSolutionConverter种的抽象方法,必须实现,用来定义基因序列的组成
Genotype<IntegerGene> genotype=Genotype.of(
IntegerChromosome.of(0, 1, IntRange.of(10)) //10个基因,每个基因只有2种可能,0或者1
); return genotype;
} public double test(AbstractSolution solution) //这个是适应度函数定义,要注意入参和出参,这2个是固定的
{ //test是method名,待会会在后面介绍,会在其他class中指定过来
Demo1Solution s=(Demo1Solution)solution; long 偶数个数=s.getSelectedIds().stream().filter(f->f%2==0).count();
long 奇数个数=s.getSelectedIds().stream().filter(f->f%2!=0).count(); double score=(-偶数个数)+(+奇数个数); //score是适应度函数的分值,越小越优,由于我们希望不要奇数、只要偶数,所以偶数部分为负号、奇数部分为正号
return score;
} @Data
public class Demo1Solution extends DefaultSolution { //这个是业务解码后存放的class,很好理解 private List<Integer> selectedIds=new ArrayList<>(); @Override
public String toString() {
StringBuilder stringBuilder=new StringBuilder(); for(int id:selectedIds)
{
stringBuilder.append(id);
stringBuilder.append(", ");
} return stringBuilder.toString();
}
}
}  

然后再看看Demo1FitnessBuilder类,既:适应度函数指向类:

public class Demo1FitnessBuilder implements FitnessBuilder {
@Override
public Tuple2<Map<String, Object>, List<Tuple3<String, String, Double>>> build() { Map<String, Object> objConfigs= buildObjectAndConfigs();
List<Tuple3<String, String, Double>> fitnessConfigs=buildFitnessConfigs(); return Tuples.of(objConfigs, fitnessConfigs);
} private Map<String, Object> buildObjectAndConfigs() { Map<String, Object> configs=new HashMap<>(); Demo1SolutionConverter obj=new Demo1SolutionConverter(); //这里定义的是n个适应度函数所在的对象(此处只定义了1个,也可以多个)
configs.put("obj", obj); return configs;
} private List<Tuple3<String, String, Double>> buildFitnessConfigs() {
List<Tuple3<String, String, Double>> fitnessConfigs = new ArrayList<>(); fitnessConfigs.add(Tuples.of("obj", "test", 1D)); //obj和上面的对应,test指明了适应度函数是在obj这个对象中方法名为test的函数
//此处也可以多个
//1D代表默认权重,也可以定期较低的权重,比如:0.5D这种
   return fitnessConfigs;
}
}

  

看看程序的输出:

0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 3, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,

  

如同大家所见,GA算法的问题在于不太稳定,只能代表一种优化趋势,导致这样的原因有很多,最重要的原因还是在于智能算法一般使用的场景都是由于传统算法无能为力的场景,或者无法穷举的场景。

下面看看加大种群迭代次数是否能解决:

options.setMaxLimits(100);
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,
0, 2, 4, 6, 8,

  

算是表面解决了,但其实还有很多因素能导致不稳定,比如,我们从当前的10个数字,enlarge到50个数字,会怎样:

@Override
public Genotype<IntegerGene> loadGenotype() {
Genotype<IntegerGene> genotype=Genotype.of(
IntegerChromosome.of(0, 1, IntRange.of(50))
); return genotype;
}
0, 2, 4, 5, 6, 8, 10, 12, 14, 15, 16, 17, 18, 20, 22, 24, 26, 28, 30, 32, 34, 35, 36, 38, 40, 41, 42, 44, 46,
0, 2, 4, 6, 8, 10, 11, 12, 13, 14, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
2, 4, 5, 6, 8, 10, 12, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 6, 8, 10, 12, 14, 16, 18, 22, 24, 26, 28, 30, 32, 34, 35, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 8, 14, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 41, 42, 44, 46, 48,
0, 2, 4, 5, 6, 8, 10, 12, 14, 15, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 47, 48, 49,
0, 2, 4, 6, 8, 10, 12, 13, 14, 16, 18, 20, 22, 24, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46,
0, 2, 4, 6, 8, 10, 12, 13, 16, 18, 19, 22, 24, 26, 28, 30, 31, 32, 36, 38, 40, 42, 43, 44, 45, 46, 48,
0, 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 21, 22, 24, 25, 26, 28, 30, 32, 34, 38, 40, 42, 44, 45, 46, 48,
0, 1, 2, 4, 5, 6, 8, 10, 11, 12, 14, 16, 18, 20, 21, 22, 23, 24, 26, 28, 30, 32, 36, 38, 40, 42, 44, 46, 48,
2, 4, 6, 8, 10, 12, 14, 16, 17, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 44, 46, 48,
0, 2, 6, 8, 10, 12, 14, 18, 20, 22, 24, 26, 28, 32, 34, 36, 38, 40, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 38, 40, 42, 43, 44, 46, 48, 49,
0, 2, 4, 6, 8, 9, 10, 12, 14, 18, 22, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 45, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 22, 24, 26, 32, 34, 36, 38, 40, 42, 44, 45, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 24, 26, 28, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 13, 14, 16, 18, 20, 22, 24, 26, 28, 31, 32, 34, 38, 40, 42, 45, 46, 48,
0, 2, 4, 6, 8, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 27, 29, 30, 32, 34, 36, 38, 40, 46, 48,
0, 4, 6, 8, 10, 12, 14, 16, 20, 22, 24, 25, 26, 28, 30, 32, 34, 36, 38, 40, 44, 46, 48,
0, 2, 4, 8, 10, 12, 14, 16, 18, 20, 21, 22, 24, 26, 28, 32, 34, 36, 38, 40, 42, 44, 46, 48,

  

哇塞,简直了,这结果。。。

再来:

options.setMaxLimits(2000);
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,   

  

体会到了不确定的痛苦了吗?

再来:

//        options.setEnableMaxLimits(true);
// options.setMaxLimits(2000);
options.setEnableSteadyFitness(true); //设置为稳定适应度函数值默认
options.setSteadyFitnessValue(1000); //当连续1000次的种群迭代的最优适应度函数值都稳定的时候,稳定就是分值没有超越当前的最好分值,然后才停止算法
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,

  

遗传算法是非常耗费算力的,能其他算法就尽量其他算法来做,真的。虽然GA也有很多优点,比如:

  1. 当无法穷举时,这个算法就是好的
  2. 当数据量较少时,这个算法也挺稳定(要调好参数)
  3. 当计算什么是好,什么是坏时的逻辑是非线性的时候,GA算法也是个很好的选项

完整代码下载,带demo+自研框架+底层是jenetics

完整下载 

 

最新文章

  1. Emberjs之Observer
  2. 自己动手写中文分词解析器完整教程,并对出现的问题进行探讨和解决(附完整c#代码和相关dll文件、txt文件下载)
  3. vue 一些开发姿势
  4. Android自动化压力测试快速入门教程(图解)——MonkeyRunner
  5. CentOS系统启动过程1-10 详细叙述
  6. 从iMessage到微信,QQ离线短信服务,米聊,易信
  7. oracle连接错误
  8. 分布式文件系统FastDFS安装与配置(单机)
  9. 在 Visual Studio 调试器中指定符号 (.pdb) 和源文件
  10. 【G】系列导航
  11. C#方式操作Cookie
  12. 【摄像头】Global Shutter(全局快门)与Rolling Shutter(卷帘快门)的区别与比较
  13. C#.NET常见问题(FAQ)-如何设置控件水平对齐,垂直对齐
  14. HTML5 通过文件输入框读取文件为base64文件, 并借助canvas压缩 FileReader, files, drawImage
  15. js中常见的内置对象
  16. IOS Core Image之二
  17. 项目介绍4 y有用
  18. codeforce465DIV2——D. Fafa and Ancient Alphabet
  19. vue2.0 + vux (二)Footer组件
  20. CPP-基础:单目运算符重载

热门文章

  1. 3c数码商城
  2. python-多任务编程02-进程(processing)
  3. kotlin中使用Handler
  4. vue学习(九) 使用内联样式设置style样式
  5. Java环境变量设置:Path、CLASSPATH、JAVA_HOME的作用分别是什么?
  6. 【vagrant】第一次安装添加box报错:The box failed to unpackage properly....
  7. 什么是 PHP SimpleXML?
  8. PHP array_pop() 函数
  9. PHP is_array() 函数
  10. MOSFET 的 I / V 特性曲线