文章目录

  • 前言
  • 优化目标
  • 求解结果
  • 迭代结果可视化
  • 算法流程
  • Java代码
  • 可视化代码

前言

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

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

优化目标

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

求解结果

变量取值为:[7.996330803705318, 6.022624753356061]
最优解为:8.000608357127064

迭代结果可视化

算法流程

Java代码

import java.util.Arrays;
import java.util.Random;/*** @Author:WSKH* @ClassName:AFSA_Solve* @ClassType:* @Description:* @Date:2022/6/8/18:26* @Email:1187560563@qq.com* @Blog:https://blog.csdn.net/weixin_51545953?type=blog*/
public class AFSA_Solve {// 鱼对象class Fish {// 当前鱼的坐标(自变量数组)double[] curVars;// 当前自变量对应的目标函数值double curObjValue;// 适应度(解决最小化问题,所以适应度为目标函数值的倒数)double fit;// 全参构造public Fish(double[] curVars, double curObjValue, double fit) {this.curVars = curVars;this.curObjValue = curObjValue;this.fit = fit;}}// 算法参数// 变量个数int varNum = 2;// 最大迭代次数int maxGen = 500;// 鱼群中鱼的个数int fishNum = 300;// 每次的最大觅食次数int preyCnt = 20;// 鱼的最大感知距离double visual = 50;// 可接受的拥挤程度double crowdedRate = 0.6;// 步长数组(各个维度的步长)double[] stepArr = new double[]{6, 6};// 变量的上下界double[] ub = new double[]{1000, 1000};double[] lb = new double[]{-1000, -1000};// 随机数对象Random random = new Random();// 鱼群Fish[] fishes;// 最佳的鱼Fish bestFish;// 记录迭代过程public double[][][] positionArr;// 当前记录的行数int r;// 求解主函数public void solve() {// 初始化鱼群initFishes();// 开始迭代for (int t = 0; t < maxGen; t++) {// 聚群行为AFSwarm();report();// 追尾AFFollow();report();// 觅食AFPrey();report();}for (Fish fish : fishes) {if (fish.fit > bestFish.fit) {bestFish = fish;}}// 输出最好的结果System.out.println("变量取值为:" + Arrays.toString(bestFish.curVars));System.out.println("最优解为:" + bestFish.curObjValue);}// 移动行为(在鱼群的移动过程中,当一条鱼或几条鱼找到食物时,附近的伙伴会迅速移动并到达食物)void AFFollow() {for (int i = 0; i < fishes.length; i++) {// 探索视野内的鱼有多少条,并找到最大适应值的鱼int friendCount = 0;Fish maxFish = copyFish(fishes[i]);for (int j = 0; j < fishes.length; j++) {if (i != j && getDistance(fishes[i], fishes[j]) <= visual) {friendCount++;if (fishes[j].fit > maxFish.fit) {maxFish = copyFish(fishes[j]);}}}// 如果周围不拥挤,且两个鱼的目标函数不相等if ((double) friendCount / fishNum <= crowdedRate && Math.abs(maxFish.curObjValue - fishes[i].curObjValue) > 0.0000001) {// 尝试往最大适应值位置游Fish tempFish = copyFish(fishes[i]);double distance = getDistance(maxFish, tempFish);for (int m = 0; m < varNum; m++) {double move = (maxFish.curVars[m] - tempFish.curVars[m]) / (distance) * stepArr[m] * random.nextDouble();moveFish(tempFish, m, move);}tempFish.curObjValue = getObjValue(tempFish.curVars);tempFish.fit = 1 / tempFish.curObjValue;if (tempFish.fit > fishes[i].fit) {fishes[i] = tempFish;} else {// 否则,进行觅食AFPrey(i);}} else {// 否则,进行觅食AFPrey(i);}}}// 聚群行为(鱼群在移动的过程中会自然地成群聚集,这是一种生活习惯,可以保证群体的存在,避免危险)void AFSwarm() {for (int i = 0; i < fishes.length; i++) {// 探索视野内的鱼有多少条,并计算周围鱼群的中心double[] midPoint = new double[varNum];int friendCount = 0;for (int j = 0; j < fishes.length; j++) {if (i != j && getDistance(fishes[i], fishes[j]) <= visual) {friendCount++;for (int m = 0; m < varNum; m++) {midPoint[m] += fishes[j].curVars[m];}}}// 计算中心for (int m = 0; m < midPoint.length; m++) {midPoint[m] /= friendCount;}double objValue = getObjValue(midPoint);// 获取中心的鱼Fish midFish = new Fish(midPoint, objValue, 1 / objValue);// 如果中心不拥挤if ((double) friendCount / fishNum <= crowdedRate) {// 尝试往中心位置游Fish tempFish = copyFish(fishes[i]);double distance = getDistance(midFish, tempFish);for (int m = 0; m < varNum; m++) {double move = (midPoint[m] - tempFish.curVars[m]) / (distance) * stepArr[m] * random.nextDouble();moveFish(tempFish, m, move);}tempFish.curObjValue = getObjValue(tempFish.curVars);tempFish.fit = 1 / tempFish.curObjValue;if (tempFish.fit > fishes[i].fit) {fishes[i] = tempFish;} else {// 否则,进行觅食AFPrey(i);}} else {// 否则,进行觅食AFPrey(i);}}}// 觅食行为(这是鱼类对食物的基本生物学行为。一般来说,鱼通过视觉感知水中食物的浓度来决定向哪移动,然后选择移动的方向)void AFPrey(int i) {// 尝试觅食preyCnt次for (int j = 0; j < preyCnt; j++) {Fish tempFish = copyFish(fishes[i]);for (int m = 0; m < varNum; m++) {moveFish(tempFish, m, visual * (random.nextDouble() - 0.5) * 2);}tempFish.curObjValue = getObjValue(tempFish.curVars);tempFish.fit = 1 / tempFish.curObjValue;if (tempFish.fit > fishes[i].fit) {double distance = getDistance(tempFish, fishes[i]);// 觅食成功,向成功方向移动for (int m = 0; m < varNum; m++) {double move = (tempFish.curVars[m] - fishes[i].curVars[m]) / (distance) * stepArr[m] * random.nextDouble();moveFish(fishes[i], m, move);}fishes[i].curObjValue = getObjValue(fishes[i].curVars);fishes[i].fit = 1 / fishes[i].curObjValue;} else {// 觅食失败,随机移动for (int m = 0; m < varNum; m++) {double move = stepArr[m] * (random.nextDouble() - 0.5) * 2;moveFish(tempFish, m, move);}tempFish.curObjValue = getObjValue(tempFish.curVars);tempFish.fit = 1 / tempFish.curObjValue;if(tempFish.fit > fishes[i].fit){fishes[i] = tempFish;}}}}void AFPrey(){for (int i = 0; i < fishes.length; i++) {AFPrey(i);}}// 记录void report(){for (int i = 0; i < fishes.length; i++) {for (int j = 0; j < varNum; j++) {positionArr[r][i][j] = fishes[i].curVars[j];}}r++;}// 初始化鱼群private void initFishes() {positionArr = new double[3*maxGen][fishNum][varNum];fishes = new Fish[fishNum];for (int i = 0; i < fishNum; i++) {fishes[i] = getRandomFish();if (i == 0 || bestFish.fit < fishes[i].fit) {bestFish = copyFish(fishes[i]);}}}// 控制鱼在第m个维度上移动n个距离public void moveFish(Fish fish, int m, double n) {// 移动fish.curVars[m] += n;// 超出定义域的判断if (fish.curVars[m] < lb[m]) {fish.curVars[m] = lb[m];}if (fish.curVars[m] > ub[m]) {fish.curVars[m] = ub[m];}}// 求两条鱼之间的距离double getDistance(Fish f1, Fish 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);}// 求两点之间的距离double getDistance(double p1, double p2) {return Math.sqrt(Math.pow(p1 - p2, 2));}// 获取一个随机生成的鱼Fish getRandomFish() {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 Fish(vars.clone(), objValue, 1 / objValue);}/*** @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;}// 复制鱼Fish copyFish(Fish old) {return new Fish(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);}@Overridepublic void start(Stage primaryStage) throws Exception {// 调用算法获取绘图数据AFSA_Solve solver = new AFSA_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);}}}

【运筹优化】AFSA人工鱼群算法求解无约束多元函数最值(Java代码实现)相关推荐

  1. 【运筹优化】CSO蟑螂算法求解无约束多元函数最值(Java代码实现)

    文章目录 一.前言 二.优化目标 三.求解结果 四.迭代结果可视化 五.算法流程图 六.Java代码实现 6.1 算法部分代码 6.2 可视化部分代码 一.前言 本文以求解二元函数最小值为例,如果需要 ...

  2. 【运筹优化】MFO飞蛾扑火算法求解无约束多元函数最值(Java代码实现)

    文章目录 前言 优化目标 求解结果 搜索过程可视化 Java算法代码 可视化代码 前言 本文以求解二元函数最小值为例,如果需要求解多元函数,只需要修改以下变量即可: varNum:变量维度数 ub和l ...

  3. 【运筹优化】SMO蜘蛛猴优化算法求解无约束多元函数最值(Java代码实现)

    文章目录 前言 优化目标 优化结果 迭代过程可视化 Java代码 可视化代码 优化流程(图太大了,所以放最后...) 前言 本文以求解二元函数最小值为例,如果需要求解多元函数,只需要修改以下变量即可: ...

  4. 【智能算法】FA萤火虫算法求解无约束多元函数最值(Java代码实现)

    文章目录 前言 优化目标 求解结果 搜索过程可视化 Java代码 可视化代码 前言 本文以求解二元函数最小值为例,如果需要求解多元函数,只需要修改以下变量即可: varNum:变量维度数 ub和lb: ...

  5. 【运筹优化】SOA海鸥优化算法求解无约束多元函数最值(Java代码实现)

    文章目录 前言 优化目标 求解结果 搜索过程可视化 Java算法代码 可视化代码 前言 本文以求解二元函数最小值为例,如果需要求解多元函数,只需要修改以下变量即可: varNum:变量维度数 ub和l ...

  6. 【运筹优化】SCSO沙丘猫群优化算法求解无约束多元函数最值(Java代码实现)

    文章目录 前言 优化目标 求解结果 搜索过程可视化 java算法代码 可视化代码 前言 本文以求解二元函数最小值为例,如果需要求解多元函数,只需要修改以下变量即可: varNum:变量维度数 ub和l ...

  7. 【运筹优化】DE差分进化算法求解无约束多元函数最值(Java代码实现)

    文章目录 前言 优化目标 求解结果 进化过程可视化 Java算法代码 可视化代码 前言 本文以求解二元函数最小值为例,如果需要求解多元函数,只需要修改以下变量即可: varNum:变量维度数 ub和l ...

  8. 【运筹优化】SSA樽海鞘优化算法求解无约束多元函数最值(Java代码实现)

    文章目录 前言 优化目标 求解结果 搜索过程可视化 Java算法代码 可视化代码 前言 本文以求解二元函数最小值为例,如果需要求解多元函数,只需要修改以下变量即可: varNum:变量维度数 ub和l ...

  9. 【运筹优化】蚁群算法求解二维矩形装箱问题(java代码实现)

    文章目录 1 前言 2 代码迁移 3 蚁群算法 3.1 蚂蚁类 Ant 3.2 蚁群算法类 ACO_Packing 4 运行结果 5 后话 [运筹优化]求解二维矩形装箱问题的算法合辑(Java代码实现 ...

最新文章

  1. 大宗商品(Bulk Stock)交易
  2. php学习之路五(表单验证)
  3. 【论文解读】A Survey on Visual Transformer及引文理解
  4. win7下安装Oracle10g解决方案
  5. IOS开发基础之使用Xcode12.3连线storyboard与属性
  6. 平台or职位,你怎么选?
  7. LeetCode 617合并二叉树-简单
  8. 7-3 素数对猜想 (40 分)
  9. 网络管理 之 Fedora Core 网络配置工具system-config-network介绍
  10. 二分类变量相关性分析spss_SPSS教程 | 两个有序分类变量的相关分析及SPSS操作
  11. python2.0迅雷下载_【Tomato DualWan】迅雷离线下载完美教程
  12. 无线局域网打印服务器,无线局域网环境下怎么连接网络打印机
  13. wps大纲栏显示在右边_隐藏显示word页面标记,就这么几招,你会吗?
  14. matlab rand 2 3 4,matlab随机函数rand的使用
  15. python-pandapower电力系统短路电流计算(算例3:探索一天的最佳电网运行方式))
  16. Blueprint介绍和使用
  17. 彻底关闭华为手机系统更新教程!防止系统自动更新!最详细教程!
  18. 设计模式-策略模式-java-中文版
  19. PL/SQL(显示游标):查询部门为20的(所有员工信息)
  20. 简书APP 使用产品报告

热门文章

  1. Markdown编辑器模式使用LaTex编辑数学公式入门
  2. 杨月江计算机导论答案,计算机导论课程实验教学大纲-计算机学院-华北科技学院.doc...
  3. Mac wireshark 工具下载安装
  4. vue项目——分类管理模块
  5. ZOJ:1203 Swordfish
  6. 【离散数学】数理逻辑 第一章 命题逻辑(4) 联结词的完备集
  7. 《图说VR入门》——DK2入门及其资源汇总
  8. Spring中的scope配置和@scope注解
  9. Word:公式编辑器,像Latex一样输入
  10. 工时、工期、执行时间计算方式