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

编程入门 行业动态 更新时间:2024-10-26 05:22:21

【运筹优化】ABC人工<a href=https://www.elefans.com/category/jswz/34/999827.html style=蜂群算法求解无约束多元函数最值(Java代码实现)"/>

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

文章目录

  • 一、前言
  • 二、算法流程
  • 三、优化目标
  • 四、求解结果
  • 五、蜂群觅食过程可视化
  • 六、Java代码实现
    • 6.1 算法部分代码
    • 6.2 可视化部分代码


一、前言

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

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

二、算法流程

三、优化目标

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

四、求解结果

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

五、蜂群觅食过程可视化

六、Java代码实现

本项目的所有代码均上传至 GitHub 仓库:(如果对你有帮助的话可以点个Star❤️哟~)

6.1 算法部分代码

import java.util.Arrays;
import java.util.Random;/*** @Author:WSKH* @ClassName:ABC_Solver* @ClassType:* @Description:* @Date:2022/6/8/09:40* @Email:1187560563@qq* @Blog:=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 +60return 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);}}

6.2 可视化部分代码

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* @Blog:=blog*/
public class PlotUtil extends Application {//当前的时间轴private Timeline nowTimeline;//绘图位置坐标private double[][][] positionArr;public static void main(String[] args) {launch(args);}@Overridepublic 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);}}}

更多推荐

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

本文发布于:2024-02-25 11:41:19,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1698860.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:蜂群   算法   函数   代码   无约束

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!