Python代码实现:坐标轮换法求解多维最优化问题

news2025/4/8 12:49:38

文章目录

  • 多维最优化问题
  • 坐标轮换法原理
  • 代码实现坐标轮换法
  • 坐标轮换法优缺点

多维最优化问题

此前介绍的黄金分割法和切线法都是针对一维最优化问题的解决方案。本文开始,我们将最优化问题从一维扩展到多维,暂时仍考虑无约束的优化场景。

坐标轮换法原理

问题维度扩展后,很容易想到的一个解决方案就是先将多维问题降维至一维,然后再使用之前的算法依次求解。坐标轮换法就是基于该思路所设计的一个算法,其实现流程(假设问题为2维最小化问题,更高维度可以直接类推)为

  1. 选取初始值 f ( x 0 , y 0 ) f(x_0,y_0) f(x0,y0)
  2. 沿着 x x x轴搜索,得到局部最优解: x = x 0 + h x=x_0+h x=x0+h
  3. 判断解的优化程度是否超出阈值 s s s:如果小于 s s s,直接退出;反之,继续执行第4步。
  4. 沿着 y y y轴搜索,得到局部最优解: y = y 0 + t y=y_0+t y=y0+t
  5. 判断解的优化程度是否超出阈值 s s s:如果小于 s s s,直接退出;反之,跳转执行第2步。

其中,第2步和第4步中局部最优解的求解均为一维最优化问题,其计算过程为:先使用进退法确定搜索区间,然后在该区间使用黄金分割法计算最优解。

下图为坐标轮换法的示意图。

代码实现坐标轮换法

以下以二维函数的最小化问题为例,使用Python实现了坐标轮换法。挺尴尬的,代码水平有限,两个方向的计算,进退法和黄金分割法分别使用了两个函数,所以主要关注一下逻辑吧。当然了,这么差的水平,也没必要再用Java写一遍了,以后代码水平提升后再做补充。

# 待优化函数f
def f(x, y):
    return 2 * x**2 + 3 * y**2 - 8 * x + 10


# 待优化函数g
def g(x, y):
    return 4 + 4.5 * x - 4 * y + x * x + 2 * y * y - 2 * x * y + x**4 - 2 * x * x * y


# 进退法:确定搜索区间,x方向
def advance_and_retreat_x(func, x, y, h):

    if abs(func(x, y) - func(x + h, y)) <= 1e-6:
        # 第三种情况
        x_min, x_max = x, x + h
    elif func(x, y) < func(x + h, y):
        # 第一种情况
        x_max = x + h
        lamb = 1
        while func(x - lamb * h, y) < func(x, y):
            lamb += 1
        x_min = x - lamb * h
    else:
        # 第二组情况
        x_min = x + h
        lamb = 2
        while func(x + lamb * h, y) < func(x + h, y):
            lamb += 1
        x_max = x + lamb * h

    return x_min, x_max


# 进退法:确定搜索区间,y方向
def advance_and_retreat_y(func, x, y, h):

    if abs(func(x, y) - func(x, y + h)) <= 1e-6:
        # 第三种情况
        y_min, y_max = y, y + h
    elif func(x, y) < func(x, y + h):
        # 第一种情况
        y_max = y + h
        lamb = 1
        while func(x, y - lamb * h) < func(x, y):
            lamb += 1
        y_min = y - lamb * h
    else:
        # 第二组情况
        y_min = y + h
        lamb = 2
        while func(x, y + lamb * h) < func(x, y + h):
            lamb += 1
        y_max = y + lamb * h

    return y_min, y_max


# 黄金分割法,求解x方向最优解
def golden_section_x(func, a, b, y, eps):
    # 统计迭代次数
    cnt = 0
    while b - a > eps:
        # 根据黄金分割法规则选择内部两点
        c = a + (b - a) * 0.382
        d = a + (b - a) * 0.618

        # 区间消去原理
        if func(c, y) < func(d, y):
            b = d
        else:
            a = c

        cnt += 1

    # 两点的中点定义为最优解
    return (a + b) / 2, func((a + b) / 2, y), cnt


# 黄金分割法,求解y方向最优解
def golden_section_y(func, a, b, x, eps):
    # 统计迭代次数
    cnt = 0
    while b - a > eps:
        # 根据黄金分割法规则选择内部两点
        c = a + (b - a) * 0.382
        d = a + (b - a) * 0.618

        # 区间消去原理
        if func(x, c) < func(x, d):
            b = d
        else:
            a = c

        cnt += 1

    # 两点的中点定义为最优解
    return (a + b) / 2, func(x, (a + b) / 2), cnt


# 坐标轮换法
def univariate_search(func, x, y, eps):

    # 打印初始值对应的解
    cur_best_f = func(x, y)
    iters = 0
    print('iter: {}, best_x: {}, best_y: {}, function calc: {}'.format(iters, x, y, cur_best_f))

    # 坐标轮换优化
    while True:

        iters += 1

        # x方向优化
        x_min, x_max = advance_and_retreat_x(func, x, y, 0.1)
        best_x, best_f, _ = golden_section_x(func, x_min, x_max, y, eps)
        print('iter_x: {}, best_x: {}, best_y: {}, best_f: {}'.format(iters, best_x, y, best_f))
        x = best_x

        # 退出循环判断
        if abs(best_f - cur_best_f) <= eps:
            break
        # 更新最优解
        cur_best_f = best_f

        # y方向优化
        y_min, y_max = advance_and_retreat_y(func, x, y, 0.1)
        best_y, best_f, _ = golden_section_y(func, y_min, y_max, x, eps)
        print('iter_y: {}, best_x: {}, best_y: {}, best_f: {}'.format(iters, x, best_y, best_f))
        y = best_y

        # 退出循环判断
        if abs(best_f - cur_best_f) <= eps:
            break
        # 更新最优解
        cur_best_f = best_f

    return func(x, y)


if __name__ == '__main__':

    # 实例f
    x_f, y_f, eps_f = 1, 2, 1e-3
    # 坐标轮换法计算最优解
    univariate_search(f, x_f, y_f, eps_f)

    print("===========================")

    # 实例g
    x_g, y_g, eps_g = -2, 2.2, 1e-3
    # 坐标轮换法计算最优解
    univariate_search(g, x_g, y_g, eps_g)


运行代码后,可以得到

iter: 0, best_x: 1, best_y: 2, function calc: 16
iter_x: 1, best_x: 2.000233763452192, best_y: 2, best_f: 14.000000109290703
iter_y: 1, best_x: 2.000233763452192, best_y: 0.00015399075125497154, best_f: 2.000000180430158
iter_x: 2, best_x: 1.9998462973783453, best_y: 0.00015399075125497154, best_f: 2.0000001183884457
===========================
iter: 0, best_x: -2, best_y: 2.2, function calc: 7.079999999999998
iter_x: 1, best_x: -1.311255594408947, best_y: 2.2, best_f: 1.8592504605100588
iter_y: 1, best_x: -1.311255594408947, best_y: 1.2040230144759103, best_f: -0.12451135087000331
iter_x: 2, best_x: -1.088311474688541, best_y: 1.2040230144759103, best_f: -0.45831207876525415
iter_y: 2, best_x: -1.088311474688541, best_y: 1.048100675705184, best_f: -0.5069639956625354
iter_x: 3, best_x: -1.0568821019967993, best_y: 1.048100675705184, best_f: -0.512672581153325
iter_y: 3, best_x: -1.0568821019967993, best_y: 1.0300634221854548, best_f: -0.5133235969440142

上述两个实例分别来源于实例1和实例2。对比原文的结果可知,最终结果都是吻合的,即本文的算法原理和代码实现是没有问题的。

坐标轮换法优缺点

针对多维最优化问题来说,坐标轮换法应该是非常容易理解和实现的解决方案。虽然文中的代码上不了台面,但是总归是比较容易实现的,而且全程只需要计算目标函数本身,并未引入导数等其他信息,所以计算速度非常快。

坐标轮换法的主要缺点是收敛效率很难保证。这里借网上大佬做的一张图来说明。以下三种为三类最优化问题的等高线图:针对第1种类型的问题,坐标轮换法在2次迭代后便得到了最优解;针对第2种类型的问题,6次迭代可以得到最优解;针对第三种类型的问题,坐标轮换法不收敛,无法得不到最优解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/149020.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ArrayList | 简单的洗牌算法

一个洗牌程序需要包含&#xff1a; 创建一副扑克牌&#xff08;除去大小王剩下52张&#xff0c;每种花色13张&#xff09;。洗牌&#xff0c;打乱牌的顺序。揭牌&#xff0c;每位玩家轮流揭牌&#xff0c;从洗完后的牌组中获得自己的牌。因此&#xff0c;我们可以依照以下思路来…

R 语言 4.2.2安装 WGCNA

文章目录1 WGCNA库介绍2 安装踩坑还得是官方文档这样安装我出现的问题参考AppendixA. 安装RB. 配置环境C. 修改镜像1 WGCNA库介绍 WGCNA是用于加权相关网络分析的R包&#xff0c; 相关网络越来越多地用于生物信息学应用 加权基因共表达网络分析是一种系统生物学方法&#xff0…

按键控制电源通断,实现各种设备/电脑开关机低功耗IC

前言 今天记录一下一些硬件开关电的低功耗控制ic&#xff0c;代替物理机械开关&#xff0c;后续有新的更好用的芯片会继续更新此博。 环境 every machine 参考文档 正文 一版我们选择ic&#xff0c;除了功能之外还要看一些性能&#xff0c;这里我暂时录入的功能就是一个按…

SpringCloud从入门到精通(九)

bus bus-概述 • Spring Cloud Bus 是用轻量的消息中间件将分布式的节点连接起来&#xff0c;可以用于广播配置文件的更改或 者服务的监控管理。关键的思想就是&#xff0c;消息总线可以为微服务做监控&#xff0c;也可以实现应用程序之间相通信。 • Spring Cloud Bus 可选的…

【MySQL】为什么使用B+树做索引

【MySQL】为什么使用B树做索引? 索引这个词&#xff0c;相信大多数人已经相当熟悉了&#xff0c;很多人都知道MySQL的索引主要以B树为主&#xff0c;但是要问到为什么用B树&#xff0c;恐怕很少有人能把前因后果讲述的很完整。本文就来从头到尾介绍下数据库的索引。 索引是一…

linux系统中QT控件的操作的基本方法

大家好&#xff0c;今天主要和大家聊一聊&#xff0c;如何学习QT中的控件使用方法。 目录 第一&#xff1a;QT控件基本简介 第二&#xff1a;QPushButton使用方法 第三&#xff1a;QTableWidget简介 第四&#xff1a;最终运行效果 第一&#xff1a;QT控件基本简介 老子曾说…

Rad Studio 11.2 安装 OrangeUI 组件教程

官方文档&#xff1a;http://www.orangeui.cn/components/install 本文参考官方文档进行 11 版本的安装 开始 打开 Rad Studio 11&#xff0c;点击 FIle–Open Project… 找到解压的目录下的 .groupproj 文件 出现移动端提示弹窗&#xff0c;关掉 即可 右键 点击右侧第一个程序…

大数取余公式

ab)modP[(amodP)(bmodP)]modP (ab)modP[(amodP)(bmodP)]modP欢迎使用Markdown编辑器 你好&#xff01; 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章&#xff0c;了解一下Markdown的基本语法知识。 新的改变 …

数据结构-随机化快速排序

一、概念及其介绍 快速排序由 C. A. R. Hoare 在 1960 年提出。 随机化快速排序基本思想&#xff1a;通过一趟排序将要排序的数据分割成独立的两部分&#xff0c;其中一部分的所有数据都比另外一部分的所有数据都要小&#xff0c;然后再按此方法对这两部分数据分别进行快速排…

Jenkins凭证/凭据管理详解

文章目录一、Jenkins中的凭证凭证类型凭证范围系统全局用户凭证域凭证提供者系统凭证提供者 &#xff08;Jenkins 凭证提供者&#xff0c;常用&#xff09;用户凭证提供者文件夹凭证提供者BlueOcean 凭证插件凭证存储二、管理凭证选择凭证提供者选择凭证类型通过提供者指定凭证…

JavaScript---DOM---DOM重点核心---1.8

关于DOM操作&#xff0c;我们主要针对于元素的操作。主要有创建、增、删、改、查、属性操作、事件操作。 创建 document.writeinnerHTMLcreateElement 增 appendChildinsertBefore 删 removeChild 改 主要修改dom的元素属性&#xff0c;dom元素的内容、属性、表单的值等 …

websocket的实现

websocket的实现 本文的websocket实现基于单线程Reactor网络模型的代码实现 初步了解websocket&#xff08;必读&#xff09;:参考连接 websocekt的实现基于http&#xff0c;数据传输与处理过程也很类似&#xff1a;基于reactor的http服务器 websocket握手 websocket基于T…

Python-123练习-02数值运算

文章目录1. 整数四则运算2. 除法运算3. 计算矩形面积4. 计算矩形面积结果保留两位小数5. 计算存款利息6. 计算多个垫片面积的和7. 换披萨8. 表达式求值9. 三角函数计算10. 三角形周长及面积1. 整数四则运算 描述 编写程序&#xff0c;计算2个正整数的和、差、积、商并输出。题…

2023春节祝福系列第一弹(放飞孔明灯,祝福大家身体健康)

2023年春节祝福第一弹 放飞孔明灯&#xff0c;祝福大家身体健康&#xff01; 目录 一、前言 二、一片星光闪烁的旋转星空 &#xff08;1&#xff09;、效果展示&#xff1a; &#xff08;2&#xff09;、相关源代码 &#xff08;3&#xff09;、语法解释 &#xff08;3.…

[ 数据结构 ] 堆排序--------思路、图解、代码

0 基本介绍 堆定义:首先是完全二叉树,分为大顶堆和小顶堆大顶堆:顾名思义,如果将父子节点看成一个堆(三个节点的组合),那么顶的值需要大于其两个子节点的值,即顶大;小顶堆即顶小升序排序使用大顶堆,降序使用小顶堆回顾顺序存储二叉树中,父子节点的关系为:下标为n的节点,它的左…

Java开发 - Spring框架初体验

目录 前言 了解框架的概念 Spring框架 关于Spring 在Maven中使用Spring Spring怎么管理对象 spring怎么创建对象 通过Bean注解创建对象 通过组件扫描创建对象 关于ComponentScan("xxxxxx") Spring Bean的作用域 自动装配技术 什么是自动装配 补充 Io…

MATLAB循环码编译码实验

标题循环码编译码实验一、实验目的1、掌握循环码编码原理和译码原理2、练习使用Matlab编程实现循环码编码和译码二、实验原理伴随式译码捕错译码三、实验要求1、编程实现码长n15的各种循环码的编码、译码&#xff0c;给出相应的码生成多项式、&#xff08;典型&#xff09;监督…

Java设计模式中装饰者模式/装饰者模式具体内容是什么/静态代理与装饰者模式联系与区别是什么

继续整理记录这段时间来的收获&#xff0c;详细代码可在我的Gitee仓库SpringBoot克隆下载学习使用&#xff01; 5.4 装饰者模式 5.4.1 概述 在不改变现有对象结构的情况下&#xff0c;动态给对象增加某些职责或功能的模式 5.4.2 结构 抽象构件(Component)&#xff1a;定义…

Javascript 中的堆、栈、引用和值

学透CSS-强烈推荐 Javascript 中的内存存储 栈-Stack&#xff1a; 这是当前 Javascript 线程的暂存空间。由于 Javascript 通常只有单线程&#xff0c;因此通常只有一个堆栈。堆栈的大小也是有限的。 堆-Heap &#xff0c;它是应用程序级别的动态内存存储。从堆中访问和检索…

java 手把手带你创建一个spring入门案例

查看本文 首先 您需要下载spring 如果没有安装 可以查看我的文章 java spring下载步骤 首先 我们打开idea开发工具 选择左上角 File > New > Project 如下图操作 勾选 然后点击下一步 然后我们选择项目目录 这里我直接用了个中文目录 最好不要跟我学哦 因为个人英文不…