精华内容
下载资源
问答
  • 多元函数最值求法
    千次阅读
    2021-10-10 21:35:02

    粒子群算法求解多元函数最值问题

    一、简介

    多元函数极值&最值问题通常使用导数/偏导数进行推导,这里尝试使用启发式算法进行求解近似最优解。选用粒子群算法进行求解,粒子群算法模仿鸟群觅食行为,核心思想是通过向距离食物最近的鸟集聚,不断更新速度和位置以达到最优解,即表现不好的个体通过向表现好的个体学习使得自身往好的方向转变,这里存在一个前提:所有鸟知道距离食物的远近,距离食物最近包含两部分:当前最近和历史最近。标准粒子群算法适合求解函数极值问题,在TSP、背包问题上多用混合型粒子群算法。算法详细介绍可参考【粒子群算法研究】。

    二、粒子群算法求解

    多元函数:y = ( x 1 x_1 x1+ x 2 x_2 x2)/( x 1 2 x_1^2 x12+ x 2 2 x_2^2 x22+1)

    粒子群编程求解

    import pylab as mpl 
    import random import
    matplotlib.pyplot as plt 
    mpl.rcParams['font.sans-serif'] = ['SimHei'] # 添加这条可以让图形显示中文
    
    def fitness(x):
        """
        计算适应值:y = (x1+x2)/(x1**2+x2**2+1)
        """
        x1 = x[0]
        x2 = x[1]
        y = (x1+x2)/(x1**2+x2**2+1)
        return y
    
    def update(x, p, g, w, c1, c2, v_low, v_high, vi, d, x_low, x_up):
        '''
        更新速度和位置
        '''
        # 更新速度
        vi = w * vi + c1 * random.uniform(0, 1) * (p-x) + c2 * random.uniform(0, 1) * (g-x)
        for j in range(d):
            if vi[j] >v_high:
                vi[j] = v_high
            elif vi[j] < v_low:
                vi[j] = v_low
    
        # 更新位置
        x = x +vi
        for j in range(d):
            if x[j] > x_up[j]:
                x[j] = x_up[j]
            elif x[j] < x_low[j]:
                x[j] = x_low[j]
        return x
    
    
    if __name__ == '__main__':
        # 参数
        birdNum = 20  # 粒子数量
        w = 0.2  # 惯性因子
        c1 = 0.4  # 自我认知因子
        c2 = 0.4  # 社会认知因子
        # pBest, pLine = 0, []  # 当前最优值、当前最优解,(自我认知部分)
        # gBest, gLine = 0, []  # 全局最优值、全局最优解,(社会认知部分)
        v_low = -2 #速度约束
        v_high =2
        iterMax = 100  # 迭代次数
        iterI = 1  # 当前迭代次数
        bestfit = -100000  # 记录每代最优值
        #y = (x1+x2)/(x1**2+x2**2+1)
        d = 2 #函数变量个数
        x_low = [-10, -10]#变量范围
        x_up = [10, 10]
    
        #随机生成初始解
        xs = np.array([np.array([random.uniform(x_low[0],x_up[0]),random.uniform(x_low[1],x_up[1])])
    	for i in range(birdNum)])
        v = np.array([random.uniform(v_low,v_high) for i in range(birdNum)])
        fits = np.array([fitness(x) for x in xs])
    
        fit = max(fits)
        x = xs[np.argmax(fits)]
    
        gBest = pBest = fit # 全局最优值、当前最优值
        gSolve = pSolve = x  # 全局最优解、当前最优解
        bestfit = []
        bestfit.append(gBest)
    
        while iterI <= iterMax:  # 迭代开始
            for i in range(birdNum):
                xs[i] = update(xs[i], pSolve, gSolve, w, c1, c2, v_low, v_high, v[i], d, x_low, x_up)
                fits[i] = fitness(xs[i])
    
            pBest, pSolve = max(fits), xs[np.argmax(fits)]
    
            if max(fits) >= gBest:
                gBest, gSolve = max(fits), xs[np.argmax(fits)]
    
            bestfit.append(gBest)
            print(iterI, gBest)  # 打印当前代数和最佳适应度值
            print(gSolve, pSolve)
            iterI += 1  # 迭代计数加一
    
        #迭代图
        plt.plot(range(1,len(bestfit)+1), bestfit)
        plt.xlabel("迭代次数")
        plt.ylabel("最优值")
        plt.show()
    
    

    结果
    y y y=0.7068, x 1 = 0.8701 , x 2 = 0.8287 x_1=0.8701,x_2=0.8287 x1=0.8701,x2=0.8287
    在这里插入图片描述

    更多相关内容
  • 【高数-2】多元函数最值

    千次阅读 2019-02-19 11:37:08
    最值要么等于极值点要么等于边界值点,极值点使用无约束极值,边界值有的带入有的使用拉格朗日极值    

    最值要么等于极值点要么等于边界值点,极值点使用无约束求极值,边界值有的带入有的使用拉格朗日极值法

     

     

    展开全文
  • 文章目录 粒子群算法的定义 模拟鸟类捕食 启示 算法流程图 案例1 - 求解二元函数最小值 代码 运行结果 迭代过程可视化 可视化代码 案例2 - 求解六元函数最小值 代码 运行结果 粒子群算法的定义 粒子群优化算法...


    粒子群算法的定义

    粒子群优化算法(Particle Swarm optimization,PSO)又翻译为粒子群算法、微粒群算法、或微粒群优化算法。是通过模拟鸟群觅食行为而发展起来的一种基于群体协作的随机搜索算法。通常认为它是群集智能 (Swarm intelligence, SI) 的一种。它可以被纳入多主体优化系统(Multiagent Optimization System, MAOS)。粒子群优化算法是由Eberhart博士和kennedy博士发明。

    模拟鸟类捕食

    PSO模拟鸟群的捕食行为。一群鸟在随机搜索食物,在这个区域里只有一块食物。所有的鸟都不知道食物在那里。但是他们知道当前的位置离食物还有多远。那么找到食物的最优策略是什么呢。最简单有效的就是搜寻离食物最近的鸟的周围区域。

    启示

    PSO从这种模型中得到启示并用于解决优化问题。PSO中,每个优化问题的解都是搜索空间中的一只鸟。我们称之为“粒子”。所有的粒子都有一个由被优化的函数决定的适应值(fitnessvalue),每个粒子还有一个速度决定他们飞翔的方向和距离。然后粒子们就追随当前的最优粒子在解空间中搜索。

    算法流程图

    在这里插入图片描述

    案例1 - 求解二元函数最小值

    Z = x^2 + y^2 - xy - 10x - 4y +60
    

    代码

    import java.util.Arrays;
    import java.util.Random;
    
    /**
     * @Author:WSKH
     * @ClassName:PSO_Solve
     * @ClassType:
     * @Description:
     * @Date:2022/6/6/14:59
     * @Email:1187560563@qq.com
     * @Blog:https://blog.csdn.net/weixin_51545953?type=blog
     */
    public class PSO_Solve {
    
        // 粒子对象
        class Particle {
            // 粒子速度数组(每个方向都有一个速度)
            double[] vArr;
            // 当前粒子坐标(自变量数组)
            double[] curVars;
            // 当前自变量对应的目标函数值
            double curObjValue;
            // 该粒子找到过的最佳目标函数值
            double bestObjValue;
            // 该粒子最好位置时的坐标
            double[] bestVars;
            // 全参构造
            public Particle(double[] vArr, double[] curVars, double curObjValue, double bestObjValue, double[] bestVars) {
                this.vArr = vArr;
                this.curVars = curVars;
                this.curObjValue = curObjValue;
                this.bestObjValue = bestObjValue;
                this.bestVars = bestVars;
            }
        }
    
        // 粒子数量
        int n = 500;
        // 每个粒子的个体学习因子:自我认知,设置较大则不容易被群体带入局部最优,但会减缓收敛速度
        double c1 = 2;
        // 每个粒子的社会学习因子:社会认知,设置较大则加快收敛,但容易陷入局部最优
        double c2 = 2;
        // 粒子的惯性权重
        double w = 0.9;
        // 迭代的次数
        int MaxGen = 500;
        // 粒子的每个维度上的最大速度(数组)
        double[] vMaxArr = new double[]{1.2,1.2};
        // 随机数对象
        Random random = new Random();
        // 自变量个数
        int varNum = 2;
        // 自变量的上下界数组
        double[] lbArr = new double[]{-1000, -1000};
        double[] ubArr = new double[]{1000, 1000};
        // 粒子群
        Particle[] particles;
        // 最佳粒子
        Particle bestParticle;
        // 记录迭代过程
        public double[][][] positionArr;
    
        /**
         * @Description 初始化粒子的位置和速度
         */
        private void initParticles() {
            // 初始化粒子群
            particles = new Particle[n];
            // 随机生成粒子
            for (int i = 0; i < particles.length; i++) {
                // 随机生成坐标和速度
                double[] vars = new double[varNum];
                double[] vArr = new double[varNum];
                for (int j = 0; j < varNum; j++) {
                    vars[j] = random.nextDouble() * (ubArr[j] - lbArr[j]) + lbArr[j];
                    vArr[j] = (random.nextDouble() - 0.5) * 2 * vMaxArr[j];
                }
                // 目标函数值
                double objValue = getObjValue(vars);
                particles[i] = new Particle(vArr.clone(), vars.clone(), objValue, objValue, vars.clone());
            }
            // 找到初始化粒子群中的最佳粒子
            bestParticle = copyParticle(particles[0]);
            for (int i = 1; i < particles.length; i++) {
                if (bestParticle.bestObjValue > particles[i].bestObjValue) {
                    bestParticle = copyParticle(particles[i]);
                }
            }
        }
    
        /**
         * @Description 主要求解函数
         */
        public void solve() {
            // 变量设置初步判断
            if(varNum != vMaxArr.length || varNum != lbArr.length || varNum != ubArr.length){
                throw new RuntimeException("变量维度不一致");
            }
            positionArr = new double[MaxGen][n][varNum];
            // 初始化粒子的位置和速度
            initParticles();
            // 开始迭代
            for (int i = 0; i < MaxGen; i++) {
                // 依次更新第i个粒子的速度与位置
                for (int j = 0; j < particles.length; j++) {
                    // 针对不同维度进行处理
                    for (int k = 0; k < varNum; k++) {
                        // 更新速度
                        double newV = particles[j].vArr[k] * w
                                + c1 * random.nextDouble() * (particles[j].bestVars[k] - particles[j].curVars[k])
                                + c2 * random.nextDouble() * (bestParticle.bestVars[k] - particles[j].curVars[k]);
                        // 如果速度超过了最大限制,就对其进行调整
                        if (newV < -vMaxArr[k]) {
                            newV = -vMaxArr[k];
                        } else if (newV > vMaxArr[k]) {
                            newV = vMaxArr[k];
                        }
                        // 更新第j个粒子第k个维度上的位置
                        double newPos = particles[j].curVars[k] + newV;
                        // 记录迭代过程
                        positionArr[i][j][k] = newPos;
                        // 如果位置超出了定义域,就对其进行调整
                        if(newPos < lbArr[k]){
                            newPos = lbArr[k];
                        }else if(newPos > ubArr[k]){
                            newPos = ubArr[k];
                        }
                        // 赋值回去
                        particles[j].curVars[k] = newPos;
                        particles[j].vArr[k] = newV;
                    }
                    // 更新完所有维度后,再计算第j个粒子的函数值
                    double objValueJ = getObjValue(particles[j].curVars);
                    particles[j].curObjValue = objValueJ;
                    if(objValueJ < particles[j].bestObjValue){
                        particles[j].bestVars = particles[j].curVars.clone();
                        particles[j].bestObjValue = particles[j].curObjValue;
                    }
                    if(objValueJ < bestParticle.bestObjValue){
                        bestParticle = copyParticle(particles[j]);
                    }
                }
            }
            // 迭代结束,输出最优粒子位置和函数值
            System.out.println("最优解为:"+ bestParticle.bestObjValue);
            System.out.println("最优解坐标为:"+ Arrays.toString(bestParticle.bestVars));
        }
    
        /**
         * @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;
        }
    
        // 复制粒子
        public Particle copyParticle(Particle old) {
            return new Particle(old.vArr.clone(), old.curVars.clone(), old.curObjValue, old.bestObjValue, old.bestVars.clone());
        }
    
    }
    

    运行结果

    最优解为:8.000057527138821
    最优解坐标为:[8.00430921604821, 5.995551568450099]
    求解用时:0.019 s
    

    迭代过程可视化

    在这里插入图片描述

    可视化代码

    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 {
    
            // 调用算法获取绘图数据
            PSO_Solve psoApi = new PSO_Solve();
            psoApi.solve();
            this.positionArr = psoApi.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);
            }
        }
    
    }
    

    案例2 - 求解六元函数最小值

    设六元变量分别为 a b c d e f
    目标:在变量区间范围最小化 Z = abc - bce + cd + ef - bdf
    

    代码

    import java.util.Arrays;
    import java.util.Random;
    
    /**
     * @Author:WSKH
     * @ClassName:PSO_Solve_6d
     * @ClassType:
     * @Description:
     * @Date:2022/6/6/14:59
     * @Email:1187560563@qq.com
     * @Blog:https://blog.csdn.net/weixin_51545953?type=blog
     */
    public class PSO_Solve_6d {
    
        // 粒子对象
        class Particle {
            // 粒子速度数组(每个方向都有一个速度)
            double[] vArr;
            // 当前粒子坐标(自变量数组)
            double[] curVars;
            // 当前自变量对应的目标函数值
            double curObjValue;
            // 该粒子找到过的最佳目标函数值
            double bestObjValue;
            // 该粒子最好位置时的坐标
            double[] bestVars;
    
            // 全参构造
            public Particle(double[] vArr, double[] curVars, double curObjValue, double bestObjValue, double[] bestVars) {
                this.vArr = vArr;
                this.curVars = curVars;
                this.curObjValue = curObjValue;
                this.bestObjValue = bestObjValue;
                this.bestVars = bestVars;
            }
        }
    
        // 粒子数量
        int n = 100;
        // 每个粒子的个体学习因子:自我认知,设置较大则不容易被群体带入局部最优,但会减缓收敛速度
        double c1 = 2;
        // 每个粒子的社会学习因子:社会认知,设置较大则加快收敛,但容易陷入局部最优
        double c2 = 2;
        // 粒子的惯性权重
        double w = 0.9;
        // 迭代的次数
        int MaxGen = 500;
        // 粒子的每个维度上的最大速度(数组)
        double[] vMaxArr = new double[]{1.2, 1.2, 1.2, 1.2, 1.2, 1.2};
        // 随机数对象
        Random random = new Random();
        // 自变量个数
        int varNum = 6;
        // 自变量的上下界数组
        double[] lbArr = new double[]{-1000, -1000, -1000, -1000, -1000, -1000};
        double[] ubArr = new double[]{1000, 1000, 1000, 1000, 1000, 1000};
        // 粒子群
        Particle[] particles;
        // 最佳粒子
        Particle bestParticle;
    
        /**
         * @Description 初始化粒子的位置和速度
         */
        private void initParticles() {
            // 初始化粒子群
            particles = new Particle[n];
            // 随机生成粒子
            for (int i = 0; i < particles.length; i++) {
                // 随机生成坐标和速度
                double[] vars = new double[varNum];
                double[] vArr = new double[varNum];
                for (int j = 0; j < varNum; j++) {
                    vars[j] = random.nextDouble() * (ubArr[j] - lbArr[j]) + lbArr[j];
                    vArr[j] = (random.nextDouble() - 0.5) * 2 * vMaxArr[j];
                }
                // 目标函数值
                double objValue = getObjValue(vars);
                particles[i] = new Particle(vArr.clone(), vars.clone(), objValue, objValue, vars.clone());
            }
            // 找到初始化粒子群中的最佳粒子
            bestParticle = copyParticle(particles[0]);
            for (int i = 1; i < particles.length; i++) {
                if (bestParticle.bestObjValue > particles[i].bestObjValue) {
                    bestParticle = copyParticle(particles[i]);
                }
            }
        }
    
        /**
         * @Description 主要求解函数
         */
        public void solve() {
            // 变量设置初步判断
            if (varNum != vMaxArr.length || varNum != lbArr.length || varNum != ubArr.length) {
                throw new RuntimeException("变量维度不一致");
            }
            // 初始化粒子的位置和速度
            initParticles();
            // 开始迭代
            for (int i = 0; i < MaxGen; i++) {
                // 依次更新第i个粒子的速度与位置
                for (int j = 0; j < particles.length; j++) {
                    // 针对不同维度进行处理
                    for (int k = 0; k < varNum; k++) {
                        // 更新速度
                        double newV = particles[j].vArr[k] * w
                                + c1 * random.nextDouble() * (particles[j].bestVars[k] - particles[j].curVars[k])
                                + c2 * random.nextDouble() * (bestParticle.bestVars[k] - particles[j].curVars[k]);
                        // 如果速度超过了最大限制,就对其进行调整
                        if (newV < -vMaxArr[k]) {
                            newV = -vMaxArr[k];
                        } else if (newV > vMaxArr[k]) {
                            newV = vMaxArr[k];
                        }
                        // 更新第j个粒子第k个维度上的位置
                        double newPos = particles[j].curVars[k] + newV;
                        // 如果位置超出了定义域,就对其进行调整
                        if (newPos < lbArr[k]) {
                            newPos = lbArr[k];
                        } else if (newPos > ubArr[k]) {
                            newPos = ubArr[k];
                        }
                        // 赋值回去
                        particles[j].curVars[k] = newPos;
                        particles[j].vArr[k] = newV;
                    }
                    // 更新完所有维度后,再计算第j个粒子的函数值
                    double objValueJ = getObjValue(particles[j].curVars);
                    particles[j].curObjValue = objValueJ;
                    if (objValueJ < particles[j].bestObjValue) {
                        particles[j].bestVars = particles[j].curVars.clone();
                        particles[j].bestObjValue = particles[j].curObjValue;
                    }
                    if (objValueJ < bestParticle.bestObjValue) {
                        bestParticle = copyParticle(particles[j]);
                    }
                }
            }
            // 迭代结束,输出最优粒子位置和函数值
            System.out.println("最优解为:" + bestParticle.bestObjValue);
            System.out.println("最优解坐标为:" + Arrays.toString(bestParticle.bestVars));
        }
    
        /**
         * @param vars 自变量数组
         * @return 返回目标函数值
         */
        public double getObjValue(double[] vars) {
            // 设六元变量分别为 a b c d e f
            // 目标:在变量区间范围最小化 Z = abc - bce + cd + ef - bdf
            return (vars[0] * vars[1] * vars[2] - vars[1] * vars[2] * vars[3] + vars[2] * vars[4] + vars[4] * vars[5] - vars[1] * vars[3] * vars[5]);
        }
    
        // 复制粒子
        public Particle copyParticle(Particle old) {
            return new Particle(old.vArr.clone(), old.curVars.clone(), old.curObjValue, old.bestObjValue, old.bestVars.clone());
        }
    
    }
    

    运行结果

    最优解为:-8.387035664320209E8
    最优解坐标为:[-886.8352994556639, -748.1858708041178, -560.6940636412202, 646.2689604948565, -274.97367655848336, -404.99446493036083]
    求解用时:0.028 s
    
    展开全文
  • 本文以求解二元函数最小值为例,如果需要求解多元函数,只需要修改以下变量即可: 求解结果 搜索过程可视化


    前言

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

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

    优化目标

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

    求解结果

    变量取值为:[8.00467444888266, 5.996471166439097]
    最优解为:8.000050798490747
    

    搜索过程可视化

    在这里插入图片描述

    Java算法代码

    import java.util.Arrays;
    import java.util.Random;
    
    /**
     * @Author:WSKH
     * @ClassName:SOA_Solve
     * @ClassType:
     * @Description:
     * @Date:2022/6/8/18:26
     * @Email:1187560563@qq.com
     * @Blog:https://blog.csdn.net/weixin_51545953?type=blog
     */
    public class SOA_Solve {
    
        // 海鸥对象
        class Seagull {
            // 当前海鸥的坐标(自变量数组)
            double[] curVars;
            // 当前自变量对应的目标函数值
            double curObjValue;
            // 适应度(解决最小化问题,所以适应度为目标函数值的倒数)
            double fit;
            // 全参构造
            public Seagull(double[] curVars, double curObjValue, double fit) {
                this.curVars = curVars;
                this.curObjValue = curObjValue;
                this.fit = fit;
            }
        }
    
        // 算法参数
        // 变量个数
        int varNum = 2;
        // 最大迭代次数
        int maxGen = 1000;
        // 海鸥群中海鸥的个数
        int seagullNum = 200;
        // 控制采用变量A的频率
        double fc = 2;
        // 定义螺旋形状的常量
        double u = 1;
        double v = 1;
        // 局部盘旋次数
        int localSearchCnt = 10;
        // 步长数组(各个维度的步长)
        double[] stepArr = new double[]{1.2, 1.2};
        // 变量的上下界
        double[] ub = new double[]{1000, 1000};
        double[] lb = new double[]{-1000, -1000};
        // 随机数对象
        Random random = new Random();
        // 海鸥群
        Seagull[] seagulls;
        // 最佳的海鸥
        Seagull bestSeagull;
        // 记录迭代过程
        public double[][][] positionArr;
        // 当前记录的行数
        int r;
    
        // 求解主函数
        public void solve() {
            // 初始化海鸥群
            initSeagulls();
            // 开始迭代
            for (int i = 0; i < maxGen; i++) {
                // 螺旋行为
                SpiralBehavior(i);
                report();
            }
            // 输出最好的结果
            System.out.println("变量取值为:" + Arrays.toString(bestSeagull.curVars));
            System.out.println("最优解为:" + bestSeagull.curObjValue);
        }
    
        // 螺旋行为
        void SpiralBehavior(int t) {
            for (int i = 0; i < seagulls.length; i++) {
                for (int j = 0; j < localSearchCnt; j++) {
                    Seagull tempSeagull = copySeagull(seagulls[i]);
                    double k = random.nextDouble() * 2 * Math.PI;
                    double rd = random.nextDouble();
                    for (int m = 0; m < varNum; m++) {
                        double r = u * Math.exp(k * v);
                        double x = r * Math.cos(k);
                        double y = r * Math.sin(k);
                        double z = r * k;
                        double ds = getDs(tempSeagull.curVars[m], t, m, rd);
                        double move = (ds * x * y * z) + bestSeagull.curVars[m] - tempSeagull.curVars[m];
                        moveSeagull(tempSeagull, m, move);
                    }
                    updateSeagull(tempSeagull);
                    seagulls[i] = tempSeagull;
                    if (tempSeagull.fit > bestSeagull.fit) {
                        bestSeagull = copySeagull(tempSeagull);
                    }
                }
            }
        }
    
        /**
         * @param x 当前海鸥当前维度的值
         * @param t 当前迭代数
         * @param m 当前计算的维度
         * @Description 计算Ds
         */
        double getDs(double x, int t, int m, double rd) {
            double A = fc - (t * (fc / maxGen));
            double B = 2 * A * A * rd;
            double cs = A * x;
            double ms = B * (bestSeagull.curVars[m] - x);
            return Math.abs(cs + ms);
        }
    
        // 记录
        void report() {
            for (int i = 0; i < seagulls.length; i++) {
                for (int j = 0; j < varNum; j++) {
                    positionArr[r][i][j] = seagulls[i].curVars[j];
                }
            }
            r++;
        }
    
        // 求两个海鸥之间的距离
        double getDistance(Seagull f1, Seagull 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 initSeagulls() {
            positionArr = new double[maxGen][seagullNum][varNum];
            seagulls = new Seagull[seagullNum];
            for (int i = 0; i < seagullNum; i++) {
                seagulls[i] = getRandomSeagull();
                if (i == 0 || bestSeagull.fit < seagulls[i].fit) {
                    bestSeagull = copySeagull(seagulls[i]);
                }
            }
        }
    
        // 控制海鸥在第m个维度上移动n个距离
        public void moveSeagull(Seagull seagull, int m, double n) {
            // 移动
            seagull.curVars[m] += n;
            // 超出定义域的判断
            if (seagull.curVars[m] < lb[m]) {
                seagull.curVars[m] = lb[m];
            }
            if (seagull.curVars[m] > ub[m]) {
                seagull.curVars[m] = ub[m];
            }
        }
    
        // 更新海鸥信息
        void updateSeagull(Seagull seagull) {
            double objValue = getObjValue(seagull.curVars);
            seagull.curObjValue = objValue;
            seagull.fit = 1 / objValue;
        }
    
        // 获取一个随机生成的海鸥
        Seagull getRandomSeagull() {
            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 Seagull(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;
        }
    
        // 复制海鸥
        Seagull copySeagull(Seagull old) {
            return new Seagull(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 {
    
            // 调用算法获取绘图数据
            SOA_Solve solver = new SOA_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);
            }
        }
    
    }
    
    展开全文
  • 通过自己的整合,可以用来求解多元函数最大值,保证可以运行,希望对你们有用
  • 多元函数求最值.doc

    2021-10-09 21:44:29
    多元函数求最值.doc
  • 梯度下降 梯度下降的基本思想可以类比为一个下山的过程。 假设这样一个场景:一个人被困在山上,需要从山上下来(找到山的最低点,也就是山谷)。但此时山上的浓雾很大,导致...首先,我们有一个可微分的函数。这个
  • 拉格朗日求函数最值matlab代码psets-drake-underactuated-robotics-6.832x 当然,edX的一些家庭作业当然是edX的Underactuated Robotics 6.832x用代码解决的,主要是那些涉及MATLAB的drake-distro库的工作。 因此,我...
  • 另附 在查资料阶段参考的比较好的相关博客文章分享如下: 算法流程理解 c++实现参考 C++实现参考2 问题描述: 遗传算法实现流程 一、程序设计 1、辅助类设计 A)个体类 通过类成员函数以及构造函数,实现个体的编码与...
  • matlab 单/多元函数极值

    千次阅读 2021-12-05 15:11:41
    matlab 单/多元函数极值 单元函数极值: 平时如果手算的话,就会先导数,再驻点,最终代值算出极值,如果用matlab代码的话,就可以减少很多不必要的计算。 fun=inline('0.5-x.*exp(-x.^2)'); ezplot(fun,[0,...
  • MATLAB遗传算法求函数最值

    千次阅读 2022-02-17 11:23:45
    MATLAB遗传算法求函数最值 问题 y=(x(1)2+x(2)2)0.25*(sin((50*(x(1)2+x(2)^2 ))^0.1 )+1) 的最小值。 遗传算法 简单说,就是通过模拟种群遗传繁殖与自然选择找到最好的个体。 一般情况,我们只要能把数据转化成...
  • 【高数】多元函数求极值和最值有什么不同?

    千次阅读 多人点赞 2019-08-14 22:21:12
    【高数】多元函数求极值和最值有什么不同?-定义、充分及必要条件、求法
  • 本文用多元函数的二阶泰勒展式给出了多元二次函数极值存在的充分必要条件,同时证明极值也是最值;用线性代数知识刻画了多元二次函数无极值时的特性.将这些方法和结论融人教学,设计了若干思考题.
  • §8.8 多元函数极值及其求法 一、多元函数的极值 1、多元函数极值定义 设函数在点的某个邻域内有定义,对该邻域内异于的点,如果都适合不等式 则称函数在点取极大值; 如果都适合不等式 则称函数在点取极小...
  • 使用遗传算法求解多元函数最值(实例)使用遗传算法求解多元函数最值使用遗传算法求解多元函数最值使使用用遗遗传传算算法法求求解解多多元元函函数数最最值值这是我们的待求解问题模型,下面是我们的实现代码:...
  • python实现PSO算法优化二元函数,具体代码如下所示: import numpy as np import random import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D #----------------------PSO参数设置----------...
  • 《MATLAB多元函数导数求极值或最优值Word版》由会员分享,可在线阅读,更多相关《MATLAB多元函数导数求...2 多元函数自由极值的求法3 多元函数条件极值的求法.4 学习掌握MATLAB软件有关的命令。【实验内容】求函数...
  • 本文以求解二元函数最小值为例,如果需要求解多元函数,只需要修改以下变量即可: 求解结果 蜂群觅食过程可视化
  • 函数压轴小题之多元函数最值问题.pdf
  • 各种智能算法程序以求函数最值为例-遗传算法.rar 首先声明,程序部分为原创,部分网络下载,部分为根据他人成果做细微改动。 这是本人智能控制的小作业,主要是用多种智能算法进行函数优化,包括遗传算法,蚁群...
  • 遗传算法求解多元函数最值源程序

    热门讨论 2008-12-29 17:22:08
    遗传算法入门程序,求解一个六峰驼背函数的最小值,绝对经典
  • 本资源为自己编写的遗传算法求多元函数极值的Matlab代码,共大家共同学习和研究。
  • Python实现遗传算法求函数最值

    千次阅读 2020-04-28 20:18:13
    Python实现遗传算法求函数最值 详细源代码:GA.py 1、算法过程图解 2、详细过程举例说明 (1)待求解方程 (2)确定编码方案 主要是确定编码长度: def segment_length(self): length = [] precision =[] for...
  • 多元函数凹凸性判定及最值定理

    千次阅读 2020-10-01 23:05:15
    多元函数凹凸性判定及最值定理
  • 利用MATLAB求多元函数的极值(2)

    千次阅读 2021-05-06 05:25:26
    利用MATLAB求多元函数的极值分两种情况,(1)无约束条件;(2)有约束条件。(2)有约束条件下极小值的方法:假设多变量非线性函数的数学模型为min f(x)c(x)<=0ceq(x)=0A·x<=bAeq·x<=x<=beqlb<=x<=...
  • 多元函数的极值及其求法

    千次阅读 2020-03-11 22:58:47
    一、多元函数的极值与最值 1.1、极值 1.1.1、二元函数极值定义 例如: z=x2+y2z=\sqrt{x^2+y^2}z=x2+y2​在(0,0)处取得极小值 z=−x2+y2z=-\sqrt{x^2+y^2}z=−x2+y2​在(0,0)处取得极大值 KaTeX parse error: ...
  • 1. 引言我们在中学的时候学过一元二次函数,求解时引入一个根公式,代入公式就可以得到不同的根,假如想计算一个高次方程的解,我们还能推导出根公式吗?伽罗瓦在群论中证实,五次及以上多项式方程没有显示表达...
  • 一。多元函数的极值 二、最值应用问题 三、条件极值 里面都有实例
  • 本文以求解二元函数最小值为例,如果需要求解多元函数,只需要修改以下变量即可: 求解结果 迭代结果可视化

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,305
精华内容 522
关键字:

多元函数最值求法