【智能算法】ABC人工蜂群算法求解无约束多元函数最值(Java代码实现)

本文涉及的产品
应用型负载均衡 ALB,每月750个小时 15LCU
传统型负载均衡 CLB,每月750个小时 15LCU
网络型负载均衡 NLB,每月750个小时 15LCU
简介: 【智能算法】ABC人工蜂群算法求解无约束多元函数最值(Java代码实现)

@[toc]


前言

本文以求解二元函数最小值为例,如果需要求解多元函数,只需要修改以下变量即可:

  • varNum:变量维度数
  • ub和lb:变量的上下界
  • vMaxArr:每个维度的搜索速度限制

算法流程

在这里插入图片描述

优化目标

目标:在变量区间范围最小化 Z = x^2 + y^2 - xy - 10x - 4y +60

求解结果

最佳迭代次数:54
变量取值为:[8.000855389813834, 5.999066863910713]
最优解为:8.000002400629782

蜂群觅食过程可视化

在这里插入图片描述

Java代码

import java.util.Arrays;
import java.util.Random;

/**
 * @Author:WSKH
 * @ClassName:ABC_Solver
 * @ClassType:
 * @Description:
 * @Date:2022/6/8/09:40
 * @Email:1187560563@qq.com
 * @Blog:https://blog.csdn.net/weixin_51545953?type=blog
 */
public class ABC_Solver {

    // 蜜蜂抽象父类
    class Bee {
        // 当前蜜蜂坐标(自变量数组)
        double[] curVars;
        // 当前自变量对应的目标函数值
        double curObjValue;
        // 适应度(解决最小化问题,所以适应度为目标函数值的倒数)
        double fit;
        // 搜索/试验次数
        int searchCount;
        // 全参构造
        public Bee(double[] curVars, double curObjValue, double fit, int searchCount) {
            this.curVars = curVars;
            this.curObjValue = curObjValue;
            this.fit = fit;
            this.searchCount = searchCount;
        }
    }

    // 算法参数
    // 蜂群数量
    int beeNum = 100;
    // 蜂群
    Bee[] bees;
    // 最大迭代次数
    int maxGen = 100;
    // 局部搜索次数
    int localSearchCount = 5;
    // 观察蜂阶段随机搜索次数
    int observeTimeSearchCount = 30;
    // 最大试验次数(超过此次数就说明该蜜源已经没有蜂蜜了,尽量设置大一点,可以更快的收敛)
    int maxSearchCount = 5000;
    // 随机数对象
    Random random = new Random();
    // 变量维度数
    int varNum = 2;
    // 变量的上下界
    double[] ub = new double[]{1000, 1000};
    double[] lb = new double[]{-1000, -1000};
    // 每个维度的速度限制
    double[] vMaxArr = new double[]{1.2, 1.2};
    // 最好的蜜蜂
    Bee bestBee;
    // 最佳迭代次数
    int bestT;
    // 记录迭代过程
    public double[][][] positionArr;

    // 初始化蜂群
    void initBees() {
        positionArr = new double[maxGen][beeNum][varNum];
        bees = new Bee[beeNum];
        for (int i = 0; i < beeNum; i++) {
            bees[i] = getRandomBee();
            if (i == 0) {
                bestBee = copyBee(bees[0]);
            } else {
                if (bestBee.fit < bees[i].fit) {
                    bestBee = copyBee(bees[i]);
                }
            }
        }
    }

    // 求解主函数
    public void solve() {
        // 初始化蜂群
        initBees();
        // 开始迭代
        for (int t = 0; t < maxGen; t++) {
            // 采蜜蜂阶段(随机局部搜索)
            honeyTime(t);
            // 观察蜂阶段
            observeTime(t);
            // 侦察蜂阶段
            scoutTime(t);
        }
        // 输出最好的结果
        System.out.println("最佳迭代次数:" + bestT);
        System.out.println("变量取值为:" + Arrays.toString(bestBee.curVars));
        System.out.println("最优解为:" + bestBee.curObjValue);
    }

    // 侦察蜂阶段
    private void scoutTime(int t) {
        for (int i = 0; i < bees.length; i++) {
            if(bees[i].searchCount >= maxSearchCount){
                bees[i] = getRandomBee();
                if(bees[i].fit > bestBee.fit){
                    bestBee = copyBee(bees[i]);
                    bestT = t;
                }
            }
        }
    }

    // 根据fit值进行轮盘赌随机选取蜜蜂进行局部搜索(fit值越大越可能被选中)
    private void observeTime(int t) {
        // 计算fit总和
        double totalFit = 0;
        for (Bee honeyBee : bees) {
            totalFit += honeyBee.fit;
        }
        // 轮盘赌的累计概率数组
        double[] p = new double[beeNum];
        for (int i = 0; i < p.length; i++) {
            p[i] = (bees[i].fit / totalFit) + (i == 0 ? 0 : p[i - 1]);
        }
        // 随机选取蜜蜂进行局部搜索
        for (int i = 0; i < observeTimeSearchCount; i++) {
            double r = random.nextDouble();
            for (int j = 0; j < p.length; j++) {
                if (r <= p[j]) {
                    localSearch(t, j);
                    break;
                }
            }
        }
    }

    // 采蜜蜂阶段(对每个蜜蜂进行随机局部搜索)
    private void honeyTime(int t) {
        for (int j = 0; j < beeNum; j++) {
            localSearch(t, j);
        }
    }

    // 随机局部搜索
    void localSearch(int t, int j) {
        Bee localBee = copyBee(bees[j]);
        for (int k = 0; k < localSearchCount; k++) {
            Bee tempBee = copyBee(localBee);
            for (int m = 0; m < tempBee.curVars.length; m++) {
                moveBee(tempBee, m, (random.nextDouble() - 0.5) * 2 * vMaxArr[m]);
            }
            tempBee.curObjValue = getObjValue(tempBee.curVars);
            tempBee.fit = 1 / tempBee.curObjValue;
            if (tempBee.fit > localBee.fit) {
                localBee = copyBee(tempBee);
                k = -1;
            }else {
                localBee.searchCount++;
            }
        }
        if (localBee.fit > bestBee.fit) {
            bestBee = copyBee(localBee);
            bestT = t;
        }
        bees[j] = copyBee(localBee);
        for (int m = 0; m < localBee.curVars.length; m++) {
            positionArr[t][j][m] = localBee.curVars[m];
        }
    }

    // 获取一个随机生成的蜜蜂
    Bee getRandomBee() {
        double[] vars = new double[varNum];
        for (int j = 0; j < vars.length; j++) {
            vars[j] = lb[j] + random.nextDouble() * (ub[j] - lb[j]);
        }
        double objValue = getObjValue(vars);
        return new Bee(vars.clone(), objValue, 1 / objValue, 0);
    }

    // 控制蜜蜂在第m个维度上移动n个距离
    public void moveBee(Bee bee, int m, double n) {
        // 移动
        bee.curVars[m] += n;
        // 超出定义域的判断
        if (bee.curVars[m] < lb[m]) {
            bee.curVars[m] = lb[m];
        }
        if (bee.curVars[m] > ub[m]) {
            bee.curVars[m] = ub[m];
        }
    }

    /**
     * @param vars 自变量数组
     * @return 返回目标函数值
     */
    public double getObjValue(double[] vars) {
        //目标:在变量区间范围最小化 Z = x^2 + y^2 - xy - 10x - 4y +60
        return Math.pow(vars[0], 2) + Math.pow(vars[1], 2) - vars[0] * vars[1] - 10 * vars[0] - 4 * vars[1] + 60;
    }

    // 复制蜜蜂
    Bee copyBee(Bee old) {
        return new Bee(old.curVars.clone(), old.curObjValue, old.fit, old.searchCount);
    }

}

可视化代码

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;

/**
 * @Author:WSKH
 * @ClassName:PlotUtil
 * @ClassType:
 * @Description:
 * @Date:2022/6/6/18:31
 * @Email:1187560563@qq.com
 * @Blog:https://blog.csdn.net/weixin_51545953?type=blog
 */
public class PlotUtil extends Application {

    //当前的时间轴
    private Timeline nowTimeline;
    //绘图位置坐标
    private double[][][] positionArr;

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {

        // 调用算法获取绘图数据
        ABC_Solver abc_solver = new ABC_Solver();
        abc_solver.solve();
        positionArr = abc_solver.positionArr;

        // 画图
        try {
            BorderPane root = new BorderPane();
            root.setStyle("-fx-padding: 20;");
            Scene scene = new Scene(root, 1600, 900);
            double canvasWid = 800;
            double canvasHei = 800;
            //根据画布大小缩放坐标值
            this.fixPosition(canvasWid - 100, canvasHei - 100);

            //画布和画笔
            HBox canvasHbox = new HBox();
            Canvas canvas = new Canvas();
            canvas.setWidth(canvasWid);
            canvas.setHeight(canvasHei);
            canvasHbox.setPrefWidth(canvasWid);
            canvasHbox.getChildren().add(canvas);
            canvasHbox.setAlignment(Pos.CENTER);
            canvasHbox.setStyle("-fx-spacing: 20;" +
                    "-fx-background-color: #87e775;");
            root.setTop(canvasHbox);
            GraphicsContext paintBrush = canvas.getGraphicsContext2D();

            //启动
            HBox hBox2 = new HBox();
            Button beginButton = new Button("播放迭代过程");
            hBox2.getChildren().add(beginButton);
            root.setBottom(hBox2);
            hBox2.setAlignment(Pos.CENTER);
            //启动仿真以及暂停仿真
            beginButton.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> {
                nowTimeline.play();
            });

            //创建扫描线连接动画
            nowTimeline = new Timeline();
            createAnimation(paintBrush);

            primaryStage.setScene(scene);
            primaryStage.show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 修正cityPositionArr的坐标,让画出来的点在画布内
     *
     * @param width
     * @param height
     */
    private void fixPosition(double width, double height) {
        double minX = Double.MAX_VALUE;
        double maxX = -Double.MAX_VALUE;
        double minY = Double.MAX_VALUE;
        double maxY = -Double.MAX_VALUE;

        for (int i = 0; i < this.positionArr.length; i++) {
            for (int j = 0; j < this.positionArr[0].length; j++) {
                minX = Math.min(minX, this.positionArr[i][j][0]);
                maxX = Math.max(maxX, this.positionArr[i][j][0]);
                minY = Math.min(minY, this.positionArr[i][j][1]);
                maxY = Math.max(maxY, this.positionArr[i][j][1]);
            }
        }

        double multiple = Math.max((maxX - minX) / width, (maxY - minY) / height);

        //转化为正数数
        for (int i = 0; i < this.positionArr.length; i++) {
            for (int j = 0; j < this.positionArr[0].length; j++) {
                if (minX < 0) {
                    this.positionArr[i][j][0] = this.positionArr[i][j][0] - minX;
                }
                if (minY < 0) {
                    this.positionArr[i][j][1] = this.positionArr[i][j][1] - minY;
                }
            }
        }

        for (int i = 0; i < this.positionArr.length; i++) {
            for (int j = 0; j < this.positionArr[0].length; j++) {
                this.positionArr[i][j][0] = this.positionArr[i][j][0] / multiple;
                this.positionArr[i][j][1] = this.positionArr[i][j][1] / multiple;
            }
        }

    }

    /**
     * 用画笔在画布上画出所有的孔
     * 画第i代的所有粒子
     */
    private void drawAllCircle(GraphicsContext paintBrush, int i) {
        paintBrush.clearRect(0, 0, 2000, 2000);
        paintBrush.setFill(Color.RED);
        for (int j = 0; j < this.positionArr[i].length; j++) {
            drawCircle(paintBrush, i, j);
        }
    }

    /**
     * 用画笔在画布上画出一个孔
     * 画第i代的第j个粒子
     */
    private void drawCircle(GraphicsContext paintBrush, int i, int j) {
        double x = this.positionArr[i][j][0];
        double y = this.positionArr[i][j][1];
        double radius = 2;
        // 圆的直径
        double diameter = radius * 2;
        paintBrush.fillOval(x, y, diameter, diameter);
    }

    /**
     * 创建动画
     */
    private void createAnimation(GraphicsContext paintBrush) {
        for (int i = 0; i < this.positionArr[0].length; i++) {
            int finalI = i;
            KeyFrame keyFrame = new KeyFrame(Duration.seconds(i * 0.05), event -> drawAllCircle(paintBrush, finalI));
            nowTimeline.getKeyFrames().add(keyFrame);
        }
    }

}
相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
目录
相关文章
|
1月前
|
机器学习/深度学习 算法 机器人
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
190 0
|
2月前
|
存储 算法 调度
【复现】【遗传算法】考虑储能和可再生能源消纳责任制的售电公司购售电策略(Python代码实现)
【复现】【遗传算法】考虑储能和可再生能源消纳责任制的售电公司购售电策略(Python代码实现)
177 26
|
2月前
|
存储 编解码 算法
【多光谱滤波器阵列设计的最优球体填充】使用MSFA设计方法进行各种重建算法时,图像质量可以提高至多2 dB,并在光谱相似性方面实现了显著提升(Matlab代码实现)
【多光谱滤波器阵列设计的最优球体填充】使用MSFA设计方法进行各种重建算法时,图像质量可以提高至多2 dB,并在光谱相似性方面实现了显著提升(Matlab代码实现)
127 6
|
1月前
|
机器学习/深度学习 算法 机器人
使用哈里斯角Harris和SIFT算法来实现局部特征匹配(Matlab代码实现)
使用哈里斯角Harris和SIFT算法来实现局部特征匹配(Matlab代码实现)
137 8
|
1月前
|
机器学习/深度学习 算法 自动驾驶
基于导向滤波的暗通道去雾算法在灰度与彩色图像可见度复原中的研究(Matlab代码实现)
基于导向滤波的暗通道去雾算法在灰度与彩色图像可见度复原中的研究(Matlab代码实现)
146 8
|
2月前
|
机器学习/深度学习 人工智能 搜索推荐
从零构建短视频推荐系统:双塔算法架构解析与代码实现
短视频推荐看似“读心”,实则依赖双塔推荐系统:用户塔与物品塔分别将行为与内容编码为向量,通过相似度匹配实现精准推送。本文解析其架构原理、技术实现与工程挑战,揭秘抖音等平台如何用AI抓住你的注意力。
573 7
从零构建短视频推荐系统:双塔算法架构解析与代码实现
|
1月前
|
人工智能 Java 物联网
Java与边缘AI:构建离线智能的物联网与移动应用
随着边缘计算和终端设备算力的飞速发展,AI推理正从云端向边缘端迁移。本文深入探讨如何在资源受限的边缘设备上使用Java构建离线智能应用,涵盖从模型优化、推理加速到资源管理的全流程。我们将完整展示在Android设备、嵌入式系统和IoT网关中部署轻量级AI模型的技术方案,为构建真正实时、隐私安全的边缘智能应用提供完整实践指南。
285 3
|
1月前
|
人工智能 监控 Java
Java与AI智能体:构建自主决策与工具调用的智能系统
随着AI智能体技术的快速发展,构建能够自主理解任务、制定计划并执行复杂操作的智能系统已成为新的技术前沿。本文深入探讨如何在Java生态中构建具备工具调用、记忆管理和自主决策能力的AI智能体系统。我们将完整展示从智能体架构设计、工具生态系统、记忆机制到多智能体协作的全流程,为Java开发者提供构建下一代自主智能系统的完整技术方案。
371 4
|
2月前
|
机器学习/深度学习 传感器 算法
【高创新】基于优化的自适应差分导纳算法的改进最大功率点跟踪研究(Matlab代码实现)
【高创新】基于优化的自适应差分导纳算法的改进最大功率点跟踪研究(Matlab代码实现)
218 14
|
2月前
|
机器学习/深度学习 传感器 算法
【无人车路径跟踪】基于神经网络的数据驱动迭代学习控制(ILC)算法,用于具有未知模型和重复任务的非线性单输入单输出(SISO)离散时间系统的无人车的路径跟踪(Matlab代码实现)
【无人车路径跟踪】基于神经网络的数据驱动迭代学习控制(ILC)算法,用于具有未知模型和重复任务的非线性单输入单输出(SISO)离散时间系统的无人车的路径跟踪(Matlab代码实现)
196 2

热门文章

最新文章

下一篇
oss云网关配置