java实现的通用遗传算法框架

这两天写了一个比较通用的遗传算法框架common-geneticalgorithm,之所以写这个是因为以前每次需要用到遗传算法的时候总是手写一遍,从开始写代码起到现在估计至少写了不下20次了,像matlab,python,js,go,java的版本都写过。
主要思路是将重复的代码部分,像选择算子,精英保留,种群初始化,遗传算法的参数等写在框架里,剩下的交叉、变异、个体初始化,适应度计算部分使用抽象类代替,需要用户自己实现。
下面使用这个框架计算一个函数x2+3*sin(x*y*z)+y2-z^2的最大值以及对应的x,y,z的值,这个函数的图像如下:
在这里插入图片描述
这个函数在我的两篇博客里都计算过(https://blog.csdn.net/just_do_it_123/article/details/50993439,https://blog.csdn.net/just_do_it_123/article/details/50835793)
分别用粒子群算法和遗传算法寻找到的最优解如下:
在这里插入图片描述
在这里我用我写的这个框架来计算一下,看看结果怎么样,下面是代码:

package examples;

import algorithms.CommonGA;
import algorithms.Individual;
import com.zhangm.easyutil.Tuple;


/**
 * 计算x^2+3*sin(x*y*z)+y^2-z^2的最大值,并求处于该值时x, y, z的值
 * @Author zhangming
 * @Date 2020/6/30 16:31
 */
public class SimpleIndividual extends Individual<double[], Double> {

    public SimpleIndividual() {
        double[] data = new double[] {Math.random() * 20 - 10, Math.random() * 20 - 10, Math.random() * 20 - 10};
        this.setData(data);
        this.setIndex(0.);
    }

    private double[][] bounds = new double[][] {new double[]{-10, 10}, new double[]{-10, 10}, new double[]{-10, 10}};

    @Override
    public SimpleIndividual mutate() {
        SimpleIndividual _this = this.clone();
        int dataLen = this.getData().length;
        // 随机挑选一个值发生变异
        int index = (int) Math.floor(Math.random() * dataLen);
        if (Math.random() < 0.5) {
            // 向下偏移0.1
            _this.getData()[index] -= (this.bounds[index][1] - this.bounds[index][0]) * 0.1;
            if (_this.getData()[index] < this.bounds[index][0]) {
                _this.getData()[index] = this.bounds[index][0];
            }
        } else {
            // 向上偏移0.1
            _this.getData()[index] += (this.bounds[index][1] - this.bounds[index][0]) * 0.1;
            if (_this.getData()[index] > this.bounds[index][1]) {
                _this.getData()[index] = this.bounds[index][1];
            }
        }
        return _this;
    }

    @Override
    public void calculateIndex() {
        // 计算指标
        double x = this.getData()[0];
        double y = this.getData()[1];
        double z = this.getData()[2];
        this.setIndex(x * x + 3 * Math.sin(x * y * z) + y * y - z * z);
    }

    @Override
    public SimpleIndividual clone() {
        double[] data = new double[3];
        System.arraycopy(this.getData(), 0, data, 0, 3);
        double index = this.getIndex();
        SimpleIndividual newIndividual = new SimpleIndividual();
        newIndividual.setData(data);
        newIndividual.setIndex(index);
        return newIndividual;
    }

    public static void main(String[] args) {
        CommonGA.CrossFunction<double[], Double> crossFunction = (Individual<double[], Double> individual1, Individual<double[], Double> individual2) -> {
            int index = (int) Math.floor(Math.random() * 3);
            Individual<double[], Double> newIndividual1 = individual1.clone();
            Individual<double[], Double> newIndividual2 = individual2.clone();
            newIndividual1.getData()[index] = individual2.getData()[index];
            newIndividual2.getData()[index] = individual1.getData()[index];
            return new Tuple<>(newIndividual1, newIndividual2);
        };

        CommonGA.InitFunction<double[], Double> initFunction = SimpleIndividual::new;

        // 由于算法以小为优,此处取最大值
        CommonGA.ComparatorFunction<double[], Double> comparatorFunction = () -> (individual1, individual2) ->
            individual1.getIndex() < individual2.getIndex() ? 1 : individual1.getIndex().equals(individual2.getIndex()) ? 0 : -1;

        CommonGA<double[], Double> ga = CommonGA.of(SimpleIndividual.class, crossFunction, comparatorFunction, initFunction)
                .withGeneralSize(200).withPopSize(100);
        ga.start();
        Individual<double[], Double> bestIndividual = ga.getBestIndividual();
        System.out.printf("max: %f, x: %f, y: %f, z: %f\n", bestIndividual.getIndex(),
                bestIndividual.getData()[0], bestIndividual.getData()[1], bestIndividual.getData()[2]);
    }

}

结果:

max: 202.686378, x: -10.000000, y: -10.000000, z: -0.302324

可以看到这个结果和之前求解的值很接近,使用这个框架只需要自己实现个体初始化,变异,适应度值计算,个体复制,交叉,适应度比较这几个部分的代码,剩下的框架就可以进行计算了,还是很方便的。项目地址:

https://github.com/Mng12345/common-geneticalgorithm

欢迎大家来star一下哈,这个框架还是非常值得使用和学习的,其中关于泛型部分的设计我前前后后改了好几遍,终于像个样子了。对了,项目里有一个叫easy-util的依赖是我自己的工具包,用来操作数据很方便,项目地址见

https://github.com/Mng12345/easy-util/tree/master

热门文章

暂无图片
编程学习 ·

php编写的旅游网站

使用PHP编写一个简单的旅游网站! wampserver集成环境编写php+mysql使用最新的Bootstrap(v4.5.0)框架详细的前端功能详细的用户后台管理具体又详细的文件上传函数文件提取链接:https://pan.baidu.com/s/1EeS4o4FnoSWLQ8f_oFg0CQ 提取码:idqm
暂无图片
编程学习 ·

leetcode 124. 二叉树中的最大路径和

题目 给定一个非空二叉树,返回其最大路径和。 本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。 思路 简单题,dfs返回当前节点为一端的最大链。答案有两种情况,1 当前节点到子孙的一条链 2 当前节点为中端,…
暂无图片
编程学习 ·

《伸手系列》之分布式锁Redssion入门和源码解析

Redisson简介 Javaer都知道Jedis,Jedis是Redis的Java实现的客户端,其API提供了比较全面的Redis命令的支持。Redission也是Redis的客户端,相比于Jedis功能简单。Jedis简单使用阻塞的I/O和redis交互,Redission通过Netty支持非阻塞I/O。Jedis最新版本2.9.0是2016年的快3年了没…
暂无图片
编程学习 ·

FFMPEG编译ffplay

关键就是要有SDL安装SDL(失败)yum install -y SDL-devel编译SDL2(成功) https://blog.csdn.net/quantum7/article/details/104173159编译参数# export is must use export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:${PKG_CONFIG_PATH}pkg-config --modversion ffnvcodecC…
暂无图片
编程学习 ·

Paddle_程序员必备的数学知识_转发

程序员——必备数学知识!!!Attention 本博客转发至百度aistudio的<深度学习7日入门-cv疫情检测>,课程非常棒!本人力推! 博客转发地址:https://aistudio.baidu.com/aistudio/projectdetail/604807 课程报名地址:https://aistudio.baidu.com/aistudio/education/group/i…
暂无图片
编程学习 ·

共识算法 POW/POS

POW/POS在区块链系统中,共识算法是区块链保持数据安全、不可篡改、透明性等特色的关键技术。共识机制是区块链的灵魂,是区块链建立信任的基础。一个区块链项目选择使用何种共识机制,决定了这个项目是否能建立起完善的激励机制,从而起到鼓励更多节点参与到项目中,进而增加系…
暂无图片
编程学习 ·

C++排雷:16. #pragma warning的几种用法

#pragma warning只对当前文件有效(对于.h,对包含它的cpp也是有效的),而不是对整个工程的所有文件有效。当该文件编译结束,设置也就失去作用。 #pragma warning(push)是保存当前的编译器警告状态;#pragma warning(push, n) 存储当前报警设置,并设置报警级别为n。n为从1到…
暂无图片
编程学习 ·

可能你还无感:AI正在帮助人类的十大应用

使用人工智能(AI)技术可以带来很多好处,其中之一就是可以帮助我们从不同的角度看待社会问题。尽管业界对AI技术可能出现的滥用有很多讨论,但我们绝对不能忽视AI应用好的一方面。全球有很多复杂的问题,而AI技术提供了一种宝贵的工具,帮助人们提高能力,为一些棘手的问题找到…
暂无图片
编程学习 ·

ARM特殊寄存器详解

ARM特殊寄存器详解 arm特殊寄存器arm汇编访问特殊寄存器 可以使用MRS和MSR特殊寄存器访问指令来访问特殊寄存器。MRS:读特殊寄存器 MSR:写特殊寄存器注意:MSP、PSP也要使用特殊寄存器访问指令来操作。 PSR特殊寄存器 APSR、EPSR、IPSR寄存器xPSR特殊寄存器arm各种架构PSR比较…
暂无图片
编程学习 ·

线程

1.线程 1.什么叫做线程,跟进程之间的关系 进程:独立的cup空间运行 线程:进程中的一个执行流程,一个进程中可以包含多个线程,这些线程共享该进程提供的资源 2.创建线程(两种方式) 让这类继承Thread类 class XXX extends Thread{ public void run() Thread xx = new Threa…
暂无图片
编程学习 ·

css基础学习记录

<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>CSS</title><!--也可在head style标签里--><!--<style type="text/css">--><!--p{--><!--color: bisqu…
暂无图片
编程学习 ·

Pandas 删除指定行

定位要删除的行 需求:删除指定列中NaN所在行。如下图,’open‘ 列中有一行为NaN,定位到它,然后删除。定位:df[np.isnan(df[open])].index # 这样即可定位到所在行的index,然后对该index进行drop操作即可删除行 df.drop(df[np.isnan(df[open])].index, inplace=True)# 直接…
暂无图片
编程学习 ·

深度学习入门教程-1.1 神经网络是什么

到底什么是人工神经网络?前面提到,人工神经网络是从大脑的理解中汲取灵感而形成的。在我们的大脑中,有数十亿个神经元,它们连接成了一个神经网络。人工神经网络,结构也有些类似。许多个神经元(下图中的⚪)相连,构成了一个神经网络。人类大脑神经元细胞接收来自外部多个…
暂无图片
编程学习 ·

Anuspline气象插值

Anuspline气象插值 收集两个帖子,做到是降水的插值 https://zhuanlan.zhihu.com/p/93957062 https://www.pianshen.com/article/29901140397/
暂无图片
编程学习 ·

隐秘的角落:张东升的人生,给所有职场人提了个醒

如果说,找一个代名词来形容职场中的中年人,之前可能没有。现在,我想,“张东升”这三个字就够了! 张东升是近期大火的电视剧《隐秘的角落》的主角,在剧中,他有着两种截然不同的模样。 表面上,在学生眼里他是一个才华横溢、带来梦想的数学老师,在同事眼里他是一个忠于妻…
暂无图片
编程学习 ·

TabRow + TextView导致文字显示不完全

我们在使用表格布局TabLayout时会出一个现象:TextView显示文字时当超过屏幕换行是最后一个文字显示不完全,这个时候我们可以将Textview改成如下布局即可将android:layout_width="wrap_content"改为android:layout_width="0dp" 同时添加该属性android:lay…
暂无图片
编程学习 ·

extern随笔

extern的用法总结函数声明是可有可无的,因为函数不加修饰符默认是extern的; 全局变量在其他文件中使用时,extern关键词是必须的,如果变量在其他文件中没有extern且没有显示的初始化,则会被当成变量的定义。局部变量是不需要extern关键字描述的,而且局部变量在程序运行时才…
暂无图片
编程学习 ·

Java数据类型

数据类型 Java属于一种强类型语言 什么是强类型语言? 即要求变量的使用需要严格符合规定,要求所有变量都必须先定义后再使用,若不按规定就会报错! Java的数据类型分为两类 基本类型(primitive type) Java语言提供了八种基本类型:六种数字类型(四个整数型,两个浮点型),…