200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > 【运筹优化】SCSO沙丘猫群优化算法求解无约束多元函数最值(Java代码实现)

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

时间:2022-10-16 18:41:42

相关推荐

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

文章目录

前言优化目标求解结果搜索过程可视化java算法代码可视化代码

前言

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

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

优化目标

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

求解结果

变量取值为:[7.995989316985881, 5.997989812044098]最优解为:8.000012064207148

搜索过程可视化

java算法代码

import java.util.Arrays;import java.util.Random;/*** @Author:WSKH* @ClassName:SCSO_Solve* @ClassType:* @Description:* @Date:/6/8/18:26* @Email:1187560563@* @Blog:/weixin_51545953?type=blog*/public class SCSO_Solve {// 沙丘猫对象class Cat {// 当前沙丘猫的坐标(自变量数组)double[] curVars;// 当前自变量对应的目标函数值double curObjValue;// 适应度(解决最小化问题,所以适应度为目标函数值的倒数)double fit;// 灵敏度double sensitivity;// 全参构造public Cat(double[] curVars, double curObjValue, double fit, double sensitivity) {this.curVars = curVars;this.curObjValue = curObjValue;this.fit = fit;this.sensitivity = sensitivity;}}// 算法参数// 变量个数int varNum = 2;// 最大迭代次数int maxGen = 500;// 沙丘猫群中沙丘猫的个数int catNum = 500;// 猫的最大灵敏度double maxSensitivity = 2;// 步长数组(各个维度的步长)double[] stepArr = new double[]{1.2, 1.2};// 搜索猎物的次数int localSearchCnt = 1;// 搜索猎物的次数int localAttackCnt = 1;// 变量的上下界double[] ub = new double[]{1000, 1000};double[] lb = new double[]{-1000, -1000};// 随机数对象Random random = new Random();// 沙丘猫群Cat[] cats;// 最佳的沙丘猫Cat bestCat;// 记录迭代过程public double[][][] positionArr;// 当前记录的行数int r;// 求解主函数public void solve() {// 初始化沙丘猫群initCats();// 开始迭代for (int i = 0; i < maxGen; i++) {localSearch();report();localAttack();report();}// 输出最好的结果System.out.println("变量取值为:" + Arrays.toString(bestCat.curVars));System.out.println("最优解为:" + bestCat.curObjValue);}// 攻击猎物void localAttack() {for (int i = 0; i < cats.length; i++) {for (int n = 0; n < localAttackCnt; n++) {Cat tempCat = copyCat(cats[i]);for (int m = 0; m < varNum; m++) {double move = 0d;if (tempCat.sensitivity > 1) {move = tempCat.sensitivity * (bestCat.curVars[m] - random.nextDouble() * tempCat.curVars[m]) - tempCat.curVars[m];} else {move = bestCat.curVars[m] - Math.abs(random.nextDouble() * (bestCat.curVars[m] - tempCat.curVars[m])) * random.nextDouble() * tempCat.sensitivity - tempCat.curVars[m];}moveCat(tempCat, m, move);}updateCat(tempCat);if (tempCat.fit > cats[i].fit) {cats[i] = tempCat;if (tempCat.fit > bestCat.fit) {bestCat = copyCat(tempCat);}}}}}// 搜寻猎物void localSearch() {for (int i = 0; i < cats.length; i++) {for (int n = 0; n < localSearchCnt; n++) {Cat tempCat = copyCat(cats[i]);for (int m = 0; m < varNum; m++) {double move = tempCat.sensitivity * (bestCat.curVars[m] - random.nextDouble() * tempCat.curVars[m]) - tempCat.curVars[m];moveCat(tempCat, m, move);}updateCat(tempCat);if (tempCat.fit > cats[i].fit) {cats[i] = tempCat;if (tempCat.fit > bestCat.fit) {bestCat = copyCat(tempCat);}}}}}// 记录void report() {for (int i = 0; i < cats.length; i++) {for (int j = 0; j < varNum; j++) {positionArr[r][i][j] = cats[i].curVars[j];}}r++;}// 求两个沙丘猫之间的距离double getDistance(Cat f1, Cat 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 initCats() {positionArr = new double[2 * maxGen][catNum][varNum];cats = new Cat[catNum];for (int i = 0; i < catNum; i++) {cats[i] = getRandomCat();if (i == 0 || bestCat.fit < cats[i].fit) {bestCat = copyCat(cats[i]);}}}// 控制沙丘猫在第m个维度上移动n个距离public void moveCat(Cat cat, int m, double n) {// 移动cat.curVars[m] += n;// 超出定义域的判断if (cat.curVars[m] < lb[m]) {cat.curVars[m] = lb[m];}if (cat.curVars[m] > ub[m]) {cat.curVars[m] = ub[m];}}// 更新沙丘猫信息void updateCat(Cat cat) {double objValue = getObjValue(cat.curVars);cat.curObjValue = objValue;cat.fit = 1 / objValue;}// 获取一个随机生成的沙丘猫Cat getRandomCat() {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 Cat(vars.clone(), objValue, 1 / objValue, random.nextDouble() * maxSensitivity);}/*** @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;}// 复制沙丘猫Cat copyCat(Cat old) {return new Cat(old.curVars.clone(), old.curObjValue, old.fit, old.sensitivity);}}

可视化代码

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:/6/6/18:31* @Email:1187560563@* @Blog:/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 {// 调用算法获取绘图数据SCSO_Solve solver = new SCSO_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);}}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。