差分进化算法原理及其MATLAB/Python代码

1.算法简介

引用自:Storn R, Price K. Differential evolution–a simple and efficient heuristic for global optimization over continuous spaces[J]. Journal of global optimization, 1997, 11: 341-359.

在这里插入图片描述
今天给大家带来的是一个非常经典的智能优化算法–差分进化算法(DE),说它是现有各类优化算法的鼻祖之一也不为过(除此之外还有PSO、GA、蚁群优化算法ACO等)。小编在本科阶段打数学建模竞赛最钟情的算法就是本文介绍的差分进化算法DE,即使它似乎没那么新颖,但小编认为其核心思想与独特的算法设计值得每一位研究优化算法的同学学习,或许会启发你的idea哦~

首先简单介绍一下本文的主角,差分进化算法(Differential Evolution,简称DE)是一种用于求解优化问题的现代启发式算法,尤其擅长于解决高维、非线性、多模态的连续优化问题。DE是由Rainer Storn和Kenneth Price在1995年提出的,它是基于群体智能的策略,类似于遗传算法,但有着自己独特的优势和简化的设计。

2.整体架构流程

在了解差分进化算法之前我建议各位可以看一下有关遗传算法(GA)的原理,因为差分进化算法是基于遗传算法(GA)的改进版,这里我放个我看着还不错的讲解链接:遗传算法原理及其matlab程序实现

相对于遗传而言,其主要改进如下:(遗传算法简称GA,差分进化简称DE)

  • 编码方式:GA使用二进制编码,DE使用实数编码,DE能够直接处理连续优化问题,且无需进行编码和解码的过程。
  • 变异操作:GA的变异通过随机改变染色体上的基因来实现。DE中的变异是通过加权差分向量来生成新个体,具有更强的方向性和探索性。
  • 交叉操作:GA中的交叉操作类似于生物遗传学中的有性繁殖。DE中的交叉则更多地表现为参数混合,即在一定概率下选择突变向量或目标向量的参数,这一过程通常称为“差分交叉”。
  • 参数控制:DE控制参数较少,而GA多,DE的调参更简单。

2.1 差分进化(Differential Evolution, DE)算法概述

差分进化(DE)是一种并行直接搜索方法,它利用NP个D维参数向量作为每一代的种群,形式如下:

x i G ; i = 1 ; 2 ; . . . ; N P ( 1 ) x_i^G ; i = 1 ; 2 ; . . . ; NP \quad (1) xiG;i=1;2;...;NP(1)

其中,(G)代表代数,(NP)在整个最小化过程中保持不变。初始向量种群随机选取,应当覆盖整个参数空间。通常假定所有随机决策遵循均匀概率分布,除非另有说明。如果有初步解存在,初始种群可以通过在标称解(x_{nom};0)上加上正态分布的随机偏差来生成。

DE通过将两个种群向量之差的加权值加上第三个向量来生成新的参数向量,这一操作称为突变。突变向量的参数随后与另一个预设向量(目标向量)的参数混合,产生所谓的试用向量。这一参数混合过程常被称为交叉(crossover)。如果试用向量产生的代价函数值小于目标向量,则试用向量将在下一代中取代目标向量,这一过程称为选择。每个种群向量在一代中都必须至少一次作为目标向量,因此一代中有(NP)次竞争。

2.2 DE的基本策略具体描述如下:

2.2.1 突变

对于每个目标向量(x_i^G ; i = 1 ; 2 ; 3 ; . . . ; NP),根据下式生成突变向量:

v i G + 1 = x r 1 G + F ⋅ ( x r 2 G − x r 3 G ) ( 2 ) v_i^{G+1} = x_{r1}^G + F \cdot (x_{r2}^G - x_{r3}^G) \quad (2) viG+1=xr1G+F(xr2Gxr3G)(2)

2.2.2 交叉

为了增加扰动参数向量的多样性,引入了交叉。为此,形成试用向量:

u i G + 1 = ( u 1 i G + 1 ; u 2 i G + 1 ; . . . ; u D i G + 1 ) u_i^{G+1} = (u_{1i}^{G+1} ; u_{2i}^{G+1} ; . . . ; u_{Di}^{G+1}) uiG+1=(u1iG+1;u2iG+1;...;uDiG+1)

其中,

u j i ; G + 1 = { v j i ; G + 1 if  ( r andb ( j ) < C R ) or  j = r n b r ( i ) x j i ; G if  ( r andb ( j ) > C R ) and  j ≠ r n b r ( i ) u_j^{i;G+1} = \begin{cases} v_j^{i;G+1} & \text{if } (r \text{ andb}(j) < C_R ) \text{ or } j = r_{nbr} (i) \\ x_j^{i;G} & \text{if } (r \text{ andb}(j) > C_R ) \text{ and } j \neq r_{nbr} (i) \end{cases} uji;G+1={vji;G+1xji;Gif (r andb(j)<CR) or j=rnbr(i)if (r andb(j)>CR) and j=rnbr(i)

2.2.3 选择

为了决定是否成为下一代(G + 1)的成员,试用向量(u_i{G+1})与目标向量(x_iG)采用贪心准则进行比较。如果(u_i{G+1})产生的代价函数值小于(x_iG),则(x_i{G+1})设置为(u_i{G+1});否则,保留旧值(x_i^G)。

3.伪代码

原论文中使用了基于C语言格式的伪代码:

while (count < gen_max):  # Halt after gen_max generations.for (i=0; i<NP; i++):  # Start loop through population.a=rnd_uni() * NP; while (a==i);  # Randomly pick 3 vectors, all different.b=rnd_uni() * NP; while ((b==i || b==a));c=rnd_uni() * NP; while ((c==i || c==a || c==b));j=rnd_uni() * D;  # Randomly pick the first parameter.for (k=1; k<D; k++):  # Load D parameters into trial[].if (rnd_uni() < CR || k==D):trial[j]=x1[a][j]+F*(x1[b][j]-x1[c][j]);  # Source for trial[j] is a random vector plus weighted differential.else:trial[j]=x1[i][j];  # Trial parameter comes from target vector.j=(j+1)%D;  # Get next parameter, modulo D.score=evaluate(trial);  # Evaluate trial with your function.if (score<=cost[i]):  # If trial[] improves on x1[i][].for (j=0; j<D; j++) x2[i][j]=trial[j];  # Move trial[] to secondary array and store improved cost.else:for (j=0; j<D; j++) x2[i][j]=x1[i][j];  # Otherwise, move x1[i][] to secondary array.for (i=0; i<NP; i++):  # After each generation.for (j=0; j<D; j++) x1[i][j]=x2[i][j];  # Move secondary array into primary array.count++;  # End of generation...increment counter.

这个伪代码展示了差分进化算法的核心循环,其中包括了三个主要步骤:突变/重组、评估/选择以及种群更新。在这个循环中,首先从当前种群中随机选择三个不同的个体(a、b、c),然后对每个维度的参数进行突变和重组,生成一个新的候选解(trial)。接着,评估候选解的适应度,并与当前个体的适应度进行比较,若候选解更好,则将其替换掉当前个体。最后,在每一代结束时,将辅助数组中的个体复制回主数组,以便开始新的一代。计数器count记录了已经完成的迭代次数,当达到最大迭代次数gen_max时,算法停止。

4. MATLAB与Python代码

4.1 MATLAB 函数

function [best_solution, best_cost] = differential_evolution(evaluate_func, D, NP, F, CR, gen_max)% 差分进化算法% 输入参数:%   evaluate_func: 评估函数,用于计算解的适应度%   D: 问题的维度%   NP: 种群大小%   F: 缩放因子%   CR: 交叉率%   gen_max: 最大迭代次数% 输出参数:%   best_solution: 最优解%   best_cost: 最优解的适应度值% 初始化种群x1 = rand(NP, D);  % 随机生成初始种群x2 = zeros(NP, D);  % 用于存储新一代种群cost = zeros(NP, 1);  % 存储每个个体的适应度值% 评估初始种群for i = 1:NPcost(i) = evaluate_func(x1(i, :));endcount = 0;  % 迭代计数器while count < gen_maxfor i = 1:NP  % 对每个个体进行操作% 随机选择三个不同的向量a = randi(NP);while a == ia = randi(NP);endb = randi(NP);while b == i || b == ab = randi(NP);endc = randi(NP);while c == i || c == a || c == bc = randi(NP);end% 创建试验向量j = randi(D);  % 随机选择一个维度开始trial = x1(i, :);  % 初始化试验向量for k = 1:Dif rand() < CR || k == D  % 判断是否进行交叉% 差分变异trial(j) = x1(a, j) + F * (x1(b, j) - x1(c, j));endj = mod(j, D) + 1;  % 移动到下一个维度end% 评估试验向量trial_cost = evaluate_func(trial);% 选择:如果试验向量更优,则替换原个体if trial_cost <= cost(i)x2(i, :) = trial;cost(i) = trial_cost;elsex2(i, :) = x1(i, :);endend% 更新种群x1 = x2;count = count + 1;  % 迭代次数加1end% 找到最优解[best_cost, idx] = min(cost);best_solution = x1(idx, :);
end

4.2 Python 函数

import numpy as npdef differential_evolution(evaluate_func, D, NP, F, CR, gen_max):"""差分进化算法参数:evaluate_func : 函数评估函数,用于计算解的适应度D : int问题的维度NP : int种群大小F : float缩放因子CR : float交叉率gen_max : int最大迭代次数返回:best_solution : numpy.ndarray最优解best_cost : float最优解的适应度值"""# 初始化种群x1 = np.random.rand(NP, D)  # 随机生成初始种群x2 = np.zeros((NP, D))  # 用于存储新一代种群cost = np.zeros(NP)  # 存储每个个体的适应度值# 评估初始种群for i in range(NP):cost[i] = evaluate_func(x1[i])count = 0  # 迭代计数器while count < gen_max:for i in range(NP):  # 对每个个体进行操作# 随机选择三个不同的向量a, b, c = np.random.choice(np.delete(np.arange(NP), i), 3, replace=False)# 创建试验向量j = np.random.randint(D)  # 随机选择一个维度开始trial = x1[i].copy()  # 初始化试验向量for k in range(D):if np.random.rand() < CR or k == D-1:  # 判断是否进行交叉# 差分变异trial[j] = x1[a, j] + F * (x1[b, j] - x1[c, j])j = (j + 1) % D  # 移动到下一个维度# 评估试验向量trial_cost = evaluate_func(trial)# 选择:如果试验向量更优,则替换原个体if trial_cost <= cost[i]:x2[i] = trialcost[i] = trial_costelse:x2[i] = x1[i]# 更新种群x1 = x2.copy()count += 1  # 迭代次数加1# 找到最优解best_idx = np.argmin(cost)best_solution = x1[best_idx]best_cost = cost[best_idx]return best_solution, best_cost

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

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

相关文章

【多模态】42、LLaVA-UHD | 支持任意纵横比和大分辨率图像输入的 LLaVA

论文&#xff1a;LLaVA-UHD: an LMM Perceiving Any Aspect Ratio and High-Resolution Images 代码&#xff1a;https://github.com/thunlp/LLaVA-UHD 出处&#xff1a;清华 | 新加坡国立大学 | 中国科学院大学 一、背景 现有的很多 LMM 都是将图像处理成固定的纵横比&…

Ubuntu编译ffmpeg并添加cmake工程

文章目录 前言前提须知为什么要自己编译 FFmpeg前提软件包与工具的安装编译ffmpeg写CMakeList.txt包含ffmpeg到我们项目中 总结 前言 FFmpeg 是一个领先的多媒体框架&#xff0c;能够解码、编码、转码、复用、解复用、流化、过滤和播放几乎所有人类和机器创造的内容。FFmpeg 包…

设计模式11-原型模式

设计模式11-原型模式 写在前面对象创建模式典型模式原型模式动机结构代码推导应用特点要点总结 原型模式与工厂方法模式对比工厂方法模式原型模式什么时候用什么模式 写在前面 对象创建模式 通过对象创建模式绕开动态内存分配来避免创建过程中所导致的耦合过紧的问题。从而支…

数学建模--国赛备赛---TOPSIS算法

目录 1.准备部分 1.1提交材料 1.2MD5码相关要求 2.TOPSIS算法 2.1算法概述 2.2基本概念 2.3算法核心思想 2.4拓展思考 3.适用赛题 3.1适用赛题说明 3.2适用赛题举例 4.赛题分析 4.1指标的分类 4.2数据预处理 4.2.1区间型属性的变换 4.2.2向量规范化 4.3数据加…

基于 Three.js 的 3D 模型加载优化

作者&#xff1a;来自 vivo 互联网前端团队- Su Ning 作为一个3D的项目&#xff0c;从用户打开页面到最终模型的渲染需要经过多个流程&#xff0c;加载的时间也会比普通的H5项目要更长一些&#xff0c;从而造成大量的用户流失。为了提升首屏加载的转化率&#xff0c;需要尽可能…

IDEA的断点调试(Debug)

《IDEA破解、配置、使用技巧与实战教程》系列文章目录 第一章 IDEA破解与HelloWorld的实战编写 第二章 IDEA的详细设置 第三章 IDEA的工程与模块管理 第四章 IDEA的常见代码模板的使用 第五章 IDEA中常用的快捷键 第六章 IDEA的断点调试&#xff08;Debug&#xff09; 第七章 …

【内网安全】横向移动-Kerberos-SPN-WinRM-RDP

目录 环境介绍与横向移动前置域横向移动-WinRM-WinRS移动条件&#xff1a; 步骤0、攻击机开启winrm服务&#xff1a;1.CS探针5985端口&#xff1a;2.连接目标主机并执行命令&#xff1a;3.上线CS&MSF:4.CS内置横向移动-winrm 域横向移动-RDP简介与条件RDP横向移动连接的三种…

TCP状态转换详解

1.什么是TCP的状态转换 TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09;是一种面向连接的、可靠的、基于字节流的传输层协议。在 TCP 连接的生命周期中&#xff0c;连接的状态会随着不同阶段的通信而发生变化&#xff0c;这些变化被称为状…

嵌入式Linux入门知识点汇总-启动过程、设备树、设备框架、锁

目录 1.BootLoader启动过程? 引导加载程序(Bootloader) 补充u-boot的理解 通用的bootloader 2.系统调用过程? 3.设备驱动模型的三个重要成员? 4.驱动和设备注册是否存在先后顺序? 5.framebuffer机制? 6.字符设备和块设备的区别并分别举例? 1.字符设备 2.块设备…

SVN 服务 安装部署 Docker(compose) 方式

通过 dockerhub 或者 命令行运行 &#xff1a; docker search svn 查看 svn 的镜像 如命令行&#xff1a; [rootSGP ~]# docker search svn NAME DESCRIPTION STARS OFFICIAL AUTOMATED garethflower…

景联文科技构建高质量心理学系知识图谱,助力大模型成为心理学科专家

心理大模型正处于快速发展阶段&#xff0c;在临床应用、教育、研究等多个领域展现出巨大潜力。 心理学系知识图谱能够丰富心理大模型的认知能力&#xff0c;使其在处理心理学相关问题时更加精确、可靠和有洞察力。这对于提高心理健康服务的质量和效率、促进科学研究以及优化教育…

【Django】网上蛋糕商城后台-订单管理

概念 前面通过多篇文章以完全实现了用户在网上蛋糕商城平台上的所有功能和操作&#xff0c;从本文开始&#xff0c;实现网站的后台管理功能的介绍和操作。 导入静态资源 在static文件夹下&#xff0c;创建admin文件夹&#xff0c;在该文件夹下导入静态资源 在templates文件夹…

cs224w笔记(p5)

链接预测任务的两种类型&#xff1a;随机缺失边&#xff1b;随时间演化边。 第一种假设可以以蛋白质之间的交互作用举例&#xff0c;缺失的是研究者还没有发现的交互作用。 第二种假设可以以社交网络举例&#xff0c;随着时间流转&#xff0c;人们认识更多朋友。 基于相似性进…

zookeeper+kafka消息队列集群部署

一.消息队列 1、什么是消息队列 消息&#xff08;Message&#xff09;是指在应用间传送的数据。消息可以非常简单&#xff0c;比如只包含文本字符串&#xff0c;也可以更复杂&#xff0c;可能包含嵌入对象。 消息队列&#xff08;MessageQueue&#xff09;是一种在软件系统中用…

1、springboot3 vue3开发平台-后端-项目构建

文章目录 1. 创建项目1.1 前置环境条件1.2 项目创建 2. 模块配置2.1 父工程配置概述2.2 配置启动模块2.3 父工程相关依赖管理 1. 创建项目 1.1 前置环境条件 idea2023, jdk17 1.2 项目创建 创建父工程并删除不需要的文件目录&#xff1a; 右键父工程依次创建其他模块 最…

Windows 、Linux、MacOS 进程管理机制

本心、输入输出、结果 文章目录 Windows 、Linux、MacOS 进程管理机制前言Windows 进程管理机制Linux 进程管理macOS 进程管理内存不够了,几个操作系统如何处理Windows 、Linux、MacOS 进程管理机制 编辑 | 简简单单 Online zuozuo 地址 | https://blog.csdn.net/qq_15071263 …

【Qt】窗口

文章目录 QMainWindow菜单栏工具栏状态栏浮动窗口对话框自定义对话框Qt内置对话框QMessageBox QMainWindow Qt中的主窗口以QMainWindow表示&#xff0c;其总体结构如下&#xff1a; 菜单栏 菜单栏MenuBar&#xff0c;可包含多个菜单Menu&#xff0c;每个菜单也可以包含多个菜…

03 Git的基本使用

第3章&#xff1a;Git的基本使用 一、创建版本仓库 一&#xff09;TortoiseGit ​ 选择项目地址&#xff0c;右键&#xff0c;创建版本库 ​ 初始化git init版本库 ​ 查看是否生成.git文件&#xff08;隐藏文件&#xff09; 二&#xff09;Git ​ 选择项目地址&#xff0c…

【LeetCode】相同的树

目录 一、题目二、解法完整代码 一、题目 给你两棵二叉树的根节点 p 和 q &#xff0c;编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同&#xff0c;并且节点具有相同的值&#xff0c;则认为它们是相同的。 示例 1&#xff1a; 输入&#xff1a;p [1,2,3],…

FastGPT 知识库搜索测试功能解析

目录 一、代码解析 1.1 searchTest.ts 1.2 controller.ts 本文接上一篇文章FastGPT 知识库搜索测试功能解析 对具体代码进行解析。 一、代码解析 FastGPT 知识库的搜索测试功能主要涉及两个文件&#xff0c;分别是 searchTest.ts 和 controller.ts 文件&#xff0c;下面分…