干货 | 自适应大邻域搜索(Adaptive Large Neighborhood Search)入门到精通超详细解析-概念篇

本文主要是介绍干货 | 自适应大邻域搜索(Adaptive Large Neighborhood Search)入门到精通超详细解析-概念篇,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

01 首先来区分几个概念

关于neighborhood serach,这里有好多种衍生和变种出来的胡里花俏的算法。大家在上网搜索的过程中可能看到什么Large Neighborhood Serach,也可能看到Very Large Scale Neighborhood Search或者今天介绍的Adaptive Large Neighborhood Search。

对于这种名字相近,实则大有不同的概念,很是让小编这样的新手头疼。不过,小编喜欢凡事都要弄得清清楚楚明明白白的。为了防止大家混淆这些相近的概念,今天这里一并介绍了吧。

总体关系可以看下图:

当一个邻域搜索算法搜索的邻域随着搜索的数据规模大小而呈指数增长,或者邻域太大而不能在实际中明确搜索时,我们把这类邻域搜索算法归类为Very Large-Scale Neighborhood Search(VLSN)。

VLSN又可以分为三类:

  • Variable-depth methods
  • Network-flows based improvement algorithms
  • Efficiently solvable special cases

而Large Neighborhood Search(LNS) 则不属于以上三种类型,但是它是属于VLSN这种类型的,因为它搜索的是一个非常大的邻域。

最后呢,是Adaptive Large Neighborhood Search(ALNS),它是根据Large Neighborhood Search(LNS) 算法扩展和延伸而来(嗯,相当于爸爸和儿子的关系……)。

由于文章篇幅呢,小编这里就不给大家一一介绍了。具体内容可以看文章后面给出的参考文献。下面给大家科普几个必要的概念。

1.0 什么是Neighborhood Search(NS)

邻域搜索算法(或称为局部搜索算法)是一类非常广泛的改进算法,其在每次迭代时通过搜索当前解的“邻域”找到更优的解。 邻域搜索算法设计中的关键是邻域结构的选择,即邻域定义的方式。 根据以往的经验,邻域越大,局部最优解就越好,这样获得的全局最优解就越好。 但是,与此同时,邻域越大,每次迭代搜索邻域所需的时间也越长。 出于这个原因,除非能够以非常有效的方式搜索较大的邻域,否则启发式搜索也得不到很好的效果。

什么又是邻域呢?小编不得不再次带大家回顾一下以前的知识:

官方一点:所谓邻域,简单的说即是给定点附近其它点的集合。在距离空间中,邻域一般被定义为以给定点为圆心的一个圆;而在组合优化问题中,邻域一般定义为由给定转化规则对给定的问题域上每结点进行转化所得到的问题域上结点的集合 (太难懂了 呜呜呜…)。

通俗一点:邻域就是指对当前解进行一个操作(这个操作可以称之为邻域动作)可以得到的所有解的集合。那么不同邻域的本质区别就在于邻域动作的不同了。

邻域动作又是什么鬼?没关系,咱们在回顾一下:

邻域动作是一个函数,通过这个函数,对当前解s,产生其相应的邻居解集合。例如:对于一个bool型问题,其当前解为:s = 1001,当将邻域动作定义为翻转其中一个bit时,得到的邻居解的集合N(s)={0001,1101,1011,1000},其中N(s) ∈ S。同理,当将邻域动作定义为互换相邻bit时,得到的邻居解的集合N(s)={0101,1001,1010}。

碍于文章篇幅,小编就不再深入介绍了。不过小编给大家找了一个比较详细的定义,大家可以看看:

1.1 什么是Very Large Scale Neighborhood Search (VLSN)

正如前面所说的一样,对于一个邻域搜索算法,当其邻域大小随着输入数据的规模大小呈指数增长的时候,那么我们就可以称该邻域搜索算法为超大规模邻域搜索算法(Very Large Scale Neighborhood Search Algorithm,VLSNA )。

一些超大规模的邻域搜索方法已经运用于运筹学之中了,并且取得了不错的效果。 例如,如果将求解线性规划的单纯形算法看成邻域搜索算法的话,那么列生成算法就是一种超大规模的邻域搜索方法。 此外,用于解决许多网络流问题的方法也可以归类为超大规模的邻域搜索方法。 用于求解最小费用流问题的negative cost cycle canceling algorithm和用于求解分配问题的augmenting path algorithm就是两个例子。

有关于VLSN我们就介绍这么多啦。不过小编还是把Wikipedia上关于VLSN的定义也放上来给大家看看吧:

In mathematical optimization, neighborhood search is a technique that tries to find good or near-optimal solutions to a combinatorial optimisation problem by repeatedly transforming a current solution into a different solution in the neighborhood of the current solution. The neighborhood of a solution is a set of similar solutions obtained by relatively simple modifications to the original solution. For a very large-scale neighborhood search, the neighborhood is large and possibly exponentially sized.

The resulting algorithms can outperform algorithms using small neighborhoods because the local improvements are larger. If neighborhood searched is limited to just one or a very small number of changes from the current solution, then it can be difficult to escape from local minima, even with additional meta-heuristic techniques such as Simulated Annealing or Tabu search. In large neighborhood search techniques, the possible changes from one solution to its neighbor may allow tens or hundreds of values to change, and this means that the size of the neighborhood may itself be sufficient to allow the search process to avoid or escape local minima, though additional meta-heuristic techniques can still improve performance.

1.2 什么是Large Neighborhood Serach(LNS)

大多数邻域搜索算法都明确定义它们的邻域,如在上面1.0 节小编给出的详细定义中描述的那样。 在LNS中,邻域是由destroy和repair方法隐式定义的。destroy方法会破坏当前解的一部分,而后repair方法会对被破坏的解进行重建。destroy方法通常包含随机性的元素,以便在每次调用destroy方法时破坏解的不同部分。 那么,解x的邻域N(x)就可以定义为:首先通过利用destroy方法破坏解x,然后利用repair方法重建解x,从而得到的一系列解的集合。

1.3 什么是Adaptive Large Neighborhood Search (ALNS)

我们前面说过,ALNS是从LNS发展扩展而来的,在了解了LNS以后,我们现在来看看ALNS。ALNS在LSN的基础上,允许在同一个搜索中使用多个destroy和repair方法来获得当前解的邻域。

ALNS会为每个destroy和repair方法分配一个权重,通过该权重从而控制每个destroy和repair方法在搜索期间使用的频率。 在搜索的过程中,ALNS会对各个destroy和repair方法的权重进行动态调整,以便获得更好的邻域和解。简单点解释,ALNS和LNS不同的是,ALNS通过使用多种destroy和repair方法,然后再根据这些destroy和repair方法生成的解的质量,选择那些表现好的destroy和repair方法,再次生成邻域进行搜索。

02 ALNS具体过程

2.1 你们一定想知道destroy和repair方法是什么?

关于destroy和repair方法,这两个小老弟在LNS和ALSN中是要组合在一起使用的,待会你们就明白了。其实,一个解x经过destroy和repair方法以后,实则是相当于经过了一个邻域动作的变换。如下图所示:

上图是三个CVRP问题的解(别问我什么是CVRP问题!!!),上左表示的是当前解,上右则是经过了destroy方法以后的解(移除了6个customers),下面表示由上右的解经过repair方法以后最终形成的解(重新插入了一些customers)。

哎哎哎!等等,小编刚刚不是说当前解x经过destroy和repair方法以后生成的是一个邻域(邻居解的集合)吗?上面才生成一个解呀!

其实,上面展示的只是生成邻域中一个解的过程而已,实际整个邻域还有很多其他可能的解。比如在一个CVRP问题中,将destroy方法定义为:移除当前解x中15%的customers。假如当前的解x中有100名customers,那么就有C(100,15)= 100!/(15!×85!) =2.5×10的17次方 种移除的方式。并且,根据每一种移除方式,又可以有很多种修复的方法。这样下来,一对destroy和repair方法能生成非常多的邻居解,而这些邻居解的集合,就是邻域了。

2.2 LNS具体流程

我们说过,ALNS是由LNS扩展而来的,在了解ALNS之前,我们不妨来了解一下LNS的具体流程。下面是LNS的伪代码:

LNS算法中包含三个变量。变量xb记录目前为止获得的最优解,x则表示当前解,而xt是临时解(便于回退到之前解的状态)。函数d(·)是destroy方法,而r(·)是repair方法。详细点就是,d(x)表示破坏解x的部分,而r(x)则表示对破坏的解进行重新修复。

在第2行中,初始化了全局最优解。在第4行中,算法首先用destroy方法,然后再用repair方法来获得新的解xt。在第5行中,评估新解xt的好坏,并以此确定该新解xt是否应该成为当前新的解决x(第6行)。评估的方式因具体程序而异,可以有很多种。最简单的评估方式就只接受那些变得更优的解。

第8行检查新解x是否优于全局最优解xb。此处 c(x)表示解x的目标函数值。如果新获得的解x更优,那么第9行将会更新全局最优解xb。在第11行中,检查终止条件。

在第12行中,返回找到的全局最优解xb。

从伪代码可以注意到,LNS算法不会搜索解的整个邻域,而只是对该邻域进行采样搜索。

2.3 ALNS的具体流程

好了,介绍完了LNS的具体流程,终于到今天的主角ALSN了。在理解了LNS的基础上,理解ALSN也非常easy了。前面说过,ALSN对LNS进行了扩展,它允许在一次搜索中搜索多个邻域(使用多组不同的destroy和repair方法)。至于搜索哪个邻域呢,ALSN会根据邻域解的质量好坏,动态进行选择调整。好啦,来看伪代码:

上面就是ALNS伪代码。相对于LNS来说,新增了第4行和第12行,修改了第2行。

Ω−和Ω+分别表示destroy和repair方法的集合。

第2行中的ρ−和ρ+分别表示各个destroy和repair方法的权重集合。一开始时,所有的方法都设置相同的权重。

第4行根据ρ−和ρ+选择destroy和repair方法。至于选择哪个方法的可能性大小,是由下面公式算出的:

总的来说,权重越大,被选中的可能性越大。

除此之外,权重大小是根据destroy和repair方法的在搜索过程中的表现进行动态调整的(第12行)。具体是怎么调整的呢?这里也给大家说一说:
在ALNS完成一次迭代搜索以后,我们使用下面的函数为每组destroy和repair方法的好坏进行一个评估:

其中,ω1≥ω2≥ω3≥ω4≥0。

假如,a和b是上次迭代中使用的destroy和repair方法。那么其权重更新如下所示:

其中,λ∈[0,1],为参数。再给大家看个图:

在一个ALNS算法中,有很多个邻域,每个邻域都可以看做是一组destroy和repair方法生成的。

碍于文章篇幅原因,今天就先不上代码了。大家先把这些概念好好理解消化了先。后面小编会把代码和详细解释做成一篇篇文章推送给大家的。谢谢!

喜欢的话可以扫码关注我们的公众号【程序猿声】哦,更多精彩尽在微信公众号【程序猿声】

微信公众号

这篇关于干货 | 自适应大邻域搜索(Adaptive Large Neighborhood Search)入门到精通超详细解析-概念篇的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/161489

相关文章

最新版IDEA配置 Tomcat的详细过程

《最新版IDEA配置Tomcat的详细过程》本文介绍如何在IDEA中配置Tomcat服务器,并创建Web项目,首先检查Tomcat是否安装完成,然后在IDEA中创建Web项目并添加Web结构,接着,... 目录配置tomcat第一步,先给项目添加Web结构查看端口号配置tomcat    先检查自己的to

使用Nginx来共享文件的详细教程

《使用Nginx来共享文件的详细教程》有时我们想共享电脑上的某些文件,一个比较方便的做法是,开一个HTTP服务,指向文件所在的目录,这次我们用nginx来实现这个需求,本文将通过代码示例一步步教你使用... 在本教程中,我们将向您展示如何使用开源 Web 服务器 Nginx 设置文件共享服务器步骤 0 —

SpringBoot集成SOL链的详细过程

《SpringBoot集成SOL链的详细过程》Solanaj是一个用于与Solana区块链交互的Java库,它为Java开发者提供了一套功能丰富的API,使得在Java环境中可以轻松构建与Solana... 目录一、什么是solanaj?二、Pom依赖三、主要类3.1 RpcClient3.2 Public

在C#中合并和解析相对路径方式

《在C#中合并和解析相对路径方式》Path类提供了几个用于操作文件路径的静态方法,其中包括Combine方法和GetFullPath方法,Combine方法将两个路径合并在一起,但不会解析包含相对元素... 目录C#合并和解析相对路径System.IO.Path类幸运的是总结C#合并和解析相对路径对于 C

手把手教你idea中创建一个javaweb(webapp)项目详细图文教程

《手把手教你idea中创建一个javaweb(webapp)项目详细图文教程》:本文主要介绍如何使用IntelliJIDEA创建一个Maven项目,并配置Tomcat服务器进行运行,过程包括创建... 1.启动idea2.创建项目模板点击项目-新建项目-选择maven,显示如下页面输入项目名称,选择

Python基于火山引擎豆包大模型搭建QQ机器人详细教程(2024年最新)

《Python基于火山引擎豆包大模型搭建QQ机器人详细教程(2024年最新)》:本文主要介绍Python基于火山引擎豆包大模型搭建QQ机器人详细的相关资料,包括开通模型、配置APIKEY鉴权和SD... 目录豆包大模型概述开通模型付费安装 SDK 环境配置 API KEY 鉴权Ark 模型接口Prompt

在 VSCode 中配置 C++ 开发环境的详细教程

《在VSCode中配置C++开发环境的详细教程》本文详细介绍了如何在VisualStudioCode(VSCode)中配置C++开发环境,包括安装必要的工具、配置编译器、设置调试环境等步骤,通... 目录如何在 VSCode 中配置 C++ 开发环境:详细教程1. 什么是 VSCode?2. 安装 VSCo

Spring Boot 中整合 MyBatis-Plus详细步骤(最新推荐)

《SpringBoot中整合MyBatis-Plus详细步骤(最新推荐)》本文详细介绍了如何在SpringBoot项目中整合MyBatis-Plus,包括整合步骤、基本CRUD操作、分页查询、批... 目录一、整合步骤1. 创建 Spring Boot 项目2. 配置项目依赖3. 配置数据源4. 创建实体类

Java解析JSON的六种方案

《Java解析JSON的六种方案》这篇文章介绍了6种JSON解析方案,包括Jackson、Gson、FastJSON、JsonPath、、手动解析,分别阐述了它们的功能特点、代码示例、高级功能、优缺点... 目录前言1. 使用 Jackson:业界标配功能特点代码示例高级功能优缺点2. 使用 Gson:轻量

Java如何接收并解析HL7协议数据

《Java如何接收并解析HL7协议数据》文章主要介绍了HL7协议及其在医疗行业中的应用,详细描述了如何配置环境、接收和解析数据,以及与前端进行交互的实现方法,文章还分享了使用7Edit工具进行调试的经... 目录一、前言二、正文1、环境配置2、数据接收:HL7Monitor3、数据解析:HL7Busines