【智能算法】CSO蟑螂算法求解无约束多元函数最值(Java代码实现)

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

@[toc]


前言

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

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

优化目标

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

求解结果

变量取值为:[8.00000005186109, 5.999999963566031]
最优解为:7.999999999999986

迭代结果可视化

这收敛速度也太快了,已经和SMO相当了!
在这里插入图片描述

算法流程图

在这里插入图片描述

Java代码

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

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

    // 蟑螂对象
    class Cockroach {
        // 当前蟑螂的坐标(自变量数组)
        double[] curVars;
        // 当前自变量对应的目标函数值
        double curObjValue;
        // 适应度(解决最小化问题,所以适应度为目标函数值的倒数)
        double fit;

        // 全参构造
        public Cockroach(double[] curVars, double curObjValue, double fit) {
            this.curVars = curVars;
            this.curObjValue = curObjValue;
            this.fit = fit;
        }
    }

    // 算法参数
    // 变量个数
    int varNum = 2;
    // 最大迭代次数
    int maxGen = 1000;
    // 蟑螂群中蟑螂的个数
    int cockroachNum = 500;
    // 视野
    double visual = 50;
    // 残忍行为次数
    int ruthlessBehaviorCnt = 1;
    // 分散行为次数
    int dispersingBehaviorCnt = 30;
    // 步长数组(各个维度的步长)
    double[] stepArr = new double[]{1.2, 1.2};
    // 变量的上下界
    double[] ub = new double[]{1000, 1000};
    double[] lb = new double[]{-1000, -1000};
    // 随机数对象
    Random random = new Random();
    // 蟑螂群
    Cockroach[] cockroaches;
    // 最佳的蟑螂
    Cockroach bestCockroach;
    // 记录迭代过程
    public double[][][] positionArr;
    // 当前记录的行数
    int r;

    // 求解主函数
    public void solve() {
        // 初始化蟑螂群
        initCockroaches();
        // 开始迭代
        for (int t = 0; t < maxGen; t++) {
            // 聚集行为
            ChaseSwarmingBehavior();
            report();
            // 分散行为
            DispersingBehavior();
            report();
            // 残忍行为
            RuthlessBehavior();
            report();
        }
        // 输出最好的结果
        System.out.println("变量取值为:" + Arrays.toString(bestCockroach.curVars));
        System.out.println("最优解为:" + bestCockroach.curObjValue);
    }

    // 聚集行为
    void ChaseSwarmingBehavior() {
        // 找到个体最优
        Cockroach[] localBestCockroaches = new Cockroach[cockroachNum];
        for (int i = 0; i < cockroaches.length; i++) {
            localBestCockroaches[i] = findLocalBestCockroach(i);
            if(bestCockroach.fit < cockroaches[i].fit){
                bestCockroach = copyCockroach(cockroaches[i]);
            }
        }
        for (int i = 0; i < cockroaches.length; i++) {
            // 说明当前蟑螂就是个体最优(或接近个体最优)
            if(Math.abs(localBestCockroaches[i].curObjValue-cockroaches[i].curObjValue) <= 0.00001){
                // 那就朝着全局最优靠近
                Cockroach tempCockroach = copyCockroach(cockroaches[i]);
                for (int m = 0; m < varNum; m++) {
                    moveCockroach(tempCockroach,m,stepArr[m]*(bestCockroach.curVars[m]-tempCockroach.curVars[m]));
                }
                tempCockroach.curObjValue = getObjValue(tempCockroach.curVars);
                tempCockroach.fit = 1/tempCockroach.curObjValue;
                if(tempCockroach.fit > cockroaches[i].fit){
                    cockroaches[i] = tempCockroach;
                }
            }else{
                // 朝着个体最优移动
                Cockroach tempCockroach = copyCockroach(cockroaches[i]);
                for (int m = 0; m < varNum; m++) {
                    moveCockroach(tempCockroach,m,stepArr[m]*(localBestCockroaches[i].curVars[m]-tempCockroach.curVars[m]));
                }
                tempCockroach.curObjValue = getObjValue(tempCockroach.curVars);
                tempCockroach.fit = 1/tempCockroach.curObjValue;
                if(tempCockroach.fit > cockroaches[i].fit){
                    cockroaches[i] = tempCockroach;
                }
            }
        }
    }

    // 分散行为
    void DispersingBehavior() {
        for (int i = 0; i < cockroaches.length; i++) {
            for (int j = 0; j < dispersingBehaviorCnt; j++) {
                Cockroach tempCockroach = copyCockroach(cockroaches[i]);
                for (int m = 0; m < varNum; m++) {
                    double move = stepArr[m] * (random.nextDouble()-0.5)*2;
                    moveCockroach(tempCockroach,m,move);
                }
                if(tempCockroach.fit > cockroaches[i].fit){
                    cockroaches[i] = tempCockroach;
                    if(tempCockroach.fit > bestCockroach.fit){
                        bestCockroach = copyCockroach(tempCockroach);
                    }
                }
            }
        }
    }

    // 残忍行为
    void RuthlessBehavior() {
        for (int i = 0; i < ruthlessBehaviorCnt; i++) {
            cockroaches[random.nextInt(cockroachNum)] = copyCockroach(bestCockroach);
        }
    }

    // 寻找个体最优蟑螂
    Cockroach findLocalBestCockroach(int j) {
        Cockroach localBest = copyCockroach(cockroaches[j]);
        for (int i = 0; i < cockroaches.length; i++) {
            if (i != j) {
                if (localBest.fit < cockroaches[i].fit && getDistance(cockroaches[j], cockroaches[i]) <= visual) {
                    localBest = copyCockroach(cockroaches[i]);
                }
            }
        }
        return localBest;
    }

    // 记录
    void report() {
        for (int i = 0; i < cockroaches.length; i++) {
            for (int j = 0; j < varNum; j++) {
                positionArr[r][i][j] = cockroaches[i].curVars[j];
            }
        }
        r++;
    }

    // 求两个蟑螂之间的距离
    double getDistance(Cockroach f1, Cockroach f2) {
        double dis = 0d;
        for (int i = 0; i < varNum; i++) {
            dis += Math.pow(f1.curVars[i] - f2.curVars[i], 2);
        }
        return Math.sqrt(dis);
    }

    // 初始化蟑螂群
    private void initCockroaches() {
        positionArr = new double[3 * maxGen][cockroachNum][varNum];
        cockroaches = new Cockroach[cockroachNum];
        for (int i = 0; i < cockroachNum; i++) {
            cockroaches[i] = getRandomCockroach();
            if (i == 0 || bestCockroach.fit < cockroaches[i].fit) {
                bestCockroach = copyCockroach(cockroaches[i]);
            }
        }
    }

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

    // 获取一个随机生成的蟑螂
    Cockroach getRandomCockroach() {
        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 Cockroach(vars.clone(), objValue, 1 / objValue);
    }

    /**
     * @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;
    }

    // 复制蟑螂
    Cockroach copyCockroach(Cockroach old) {
        return new Cockroach(old.curVars.clone(), old.curObjValue, old.fit);
    }

}

可视化代码

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 {

        // 调用算法获取绘图数据
        CSO_Solve solver = new CSO_Solve();
        solver.solve();
        positionArr = 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应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
目录
相关文章
|
2月前
|
Java 数据安全/隐私保护
快手小红书抖音留痕工具,自动留痕插件工具,java代码开源
这个框架包含三个核心模块:主操作类处理点赞评论、配置管理类和代理管理类。使用时需要配合
|
1月前
|
算法 IDE Java
Java 项目实战之实际代码实现与测试调试全过程详解
本文详细讲解了Java项目的实战开发流程,涵盖项目创建、代码实现(如计算器与汉诺塔问题)、单元测试(使用JUnit)及调试技巧(如断点调试与异常排查),帮助开发者掌握从编码到测试调试的完整技能,提升Java开发实战能力。
223 0
|
2月前
|
Java 编译器 数据库连接
Java异常处理:写出更健壮的代码
Java异常处理:写出更健壮的代码
149 0
|
1月前
|
存储 SQL Java
Java 大视界 -- Java 大数据在智能医疗手术风险评估与术前方案制定中的应用探索(203)
本文探讨了Java大数据技术在智能医疗手术风险评估与术前方案制定中的创新应用。通过多源数据整合、智能分析模型构建及知识图谱技术,提升手术风险预测准确性与术前方案制定效率,助力医疗决策智能化,推动精准医疗发展。
|
2月前
|
机器学习/深度学习 Java 大数据
Java 大视界 -- Java 大数据在智能政务公共资源交易数据分析与监管中的应用(202)
本篇文章深入探讨了 Java 大数据在智能政务公共资源交易监管中的创新应用。通过构建高效的数据采集、智能分析与可视化决策系统,Java 大数据技术成功破解了传统监管中的数据孤岛、效率低下和监管滞后等难题,为公共资源交易打造了“智慧卫士”,助力政务监管迈向智能化、精准化新时代。
|
2月前
|
安全 Java 测试技术
Java 项目实战中现代技术栈下代码实现与测试调试的完整流程
本文介绍基于Java 17和Spring技术栈的现代化项目开发实践。项目采用Gradle构建工具,实现模块化DDD分层架构,结合Spring WebFlux开发响应式API,并应用Record、Sealed Class等新特性。测试策略涵盖JUnit单元测试和Testcontainers集成测试,通过JFR和OpenTelemetry实现性能监控。部署阶段采用Docker容器化和Kubernetes编排,同时展示异步处理和反应式编程的性能优化。整套方案体现了现代Java开发的最佳实践,包括代码实现、测试调试
120 0
|
2月前
|
传感器 机器学习/深度学习 算法
Java 大视界 -- Java 大数据在智能农业温室环境调控与作物生长模型构建中的应用(189)
本文探讨了Java大数据在智能农业温室环境调控与作物生长模型构建中的关键应用。通过高效采集、传输与处理温室环境数据,结合机器学习算法,实现温度、湿度、光照等参数的智能调控,提升作物产量与品质。同时,融合多源数据构建精准作物生长模型,助力农业智能化、精细化发展,推动农业现代化进程。
|
2月前
|
SQL Java 数据库连接
Java 期末考试救急必备涵盖绝大多数核心考点及五大类经典代码助你过关
本文为Java期末考试复习指南,涵盖基础语法、面向对象编程、异常处理、文件操作、数据库连接五大核心考点,提供详细解析与实用代码示例,助力快速掌握重点,高效备考,轻松应对考试。
70 0
|
24天前
|
机器学习/深度学习 算法 新能源
【优化调度】基于matlab粒子群算法求解水火电经济调度优化问题研究(Matlab代码实现)
【优化调度】基于matlab粒子群算法求解水火电经济调度优化问题研究(Matlab代码实现)

热门文章

最新文章