干货 | 自适应大邻域搜索(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)入门到精通超详细解析-概念篇的更多相关文章
- 代码 | 自适应大邻域搜索系列之(3) - Destroy和Repair方法代码实现解析
前言 上一篇文章中我们具体解剖了ALNS类的具体代码实现过程,不过也留下了很多大坑.接下来的文章基本都是"填坑"了,把各个模块一一展现解析给大家.不过碍于文章篇幅等原因呢,也不会每 ...
- 代码 | 自适应大邻域搜索系列之(6) - 判断接受准则SimulatedAnnealing的代码解析
前言 前面三篇文章对大家来说应该很简单吧?不过轻松了这么久,今天再来看点刺激的.关于判断接受准则的代码.其实,判断接受准则有很多种,效果也因代码而异.今天介绍的是模拟退火的判断接受准则.那么,相关的原 ...
- 代码 | 自适应大邻域搜索系列之(7) - 局部搜索LocalSearch的代码解析
前言 好了小伙伴们我们又见面了,咳咳没错还是我.不知道你萌接连被这么多篇代码文章刷屏是什么感受,不过,酸爽归酸爽.今天咱们依然讲代码哈~不过今天讲的依然很简单,关于局部搜索LocalSearch的代码 ...
- 自适应大邻域搜索代码系列之(1) - 使用ALNS代码框架求解TSP问题
前言 上次出了邻域搜索的各种概念科普,尤其是LNS和ALNS的具体过程更是描述得一清二楚.不知道你萌都懂了吗?小编相信大家早就get到啦.不过有个别不愿意透露姓名的热心网友表示上次没有代码,遂不过瘾啊 ...
- 代码 | 自适应大邻域搜索系列之(2) - ALNS算法主逻辑结构解析
00 前言 在上一篇推文中,教大家利用了ALNS的lib库求解了一个TSP问题作为实例.不知道你萌把代码跑起来了没有.那么,今天咱们再接再厉.跑完代码以后,小编再给大家深入讲解具体的代码内容.大家快去 ...
- 代码 | 自适应大邻域搜索系列之(5) - ALNS_Iteration_Status和ALNS_Parameters的代码解析
前言 上一篇推文说了,后面的代码难度直线下降,各位小伙伴可以放去n的100次方心了.今天讲讲一些细枝末节,就是前面一直有提到的参数和一些状态的记录代码.这个简单啦,小编也不作过多解释了.大家直接看代码 ...
- 代码 | 自适应大邻域搜索系列之(4) - Solution定义和管理的代码实现解析
前言 上一篇讲解了destroy和repair方法的具体实现代码,好多读者都在喊酸爽和得劲儿--今天这篇就讲点简单的,关于solution的定义和管理的代码实现,让大家回回神吧--哈哈. 01 总体概 ...
- 【智能算法】变邻域搜索算法(Variable Neighborhood Search,VNS)超详细解析和TSP代码实例以及01背包代码实例
喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号[程序猿声] 00 目录 局部搜索再次科普 变邻域搜索 造轮子写代码 01 局部搜索科普三连 虽然之前做的很多篇启发式的算法都有跟大家提过局部 ...
- 【优化算法】Greedy Randomized Adaptive Search算法 超详细解析,附代码实现TSP问题求解
01 概述 Greedy Randomized Adaptive Search,贪婪随机自适应搜索(GRAS),是组合优化问题中的多起点元启发式算法,在算法的每次迭代中,主要由两个阶段组成:构造(co ...
随机推荐
- 2018.06.30 BZOJ 2342: [Shoi2011]双倍回文(manacher)
2342: [Shoi2011]双倍回文 Time Limit: 10 Sec Memory Limit: 128 MB Description Input 输入分为两行,第一行为一个整数,表示字符串 ...
- 2018.09.07 codeforces311B. Cats Transport(斜率优化dp)
传送门 斜率优化dp好题. 对于第i只猫,显然如果管理员想从出发开始刚好接到它,需要在t[i]=h[i]−dist(1,i)" role="presentation" s ...
- 2018.08.19 NOIP模拟 dp(二分+状压dp)
Dp 题目背景 SOURCE:NOIP2015-SHY-10 题目描述 一块土地有 n 个连续的部分,用 H[1],H[2],-,H[n] 表示每个部分的最初高度.有 n 种泥土可用,他们都能覆盖连续 ...
- POJ 3621 Sightseeing Cows (bellman-Ford + 01分数规划)
题意:给出 n 个点 m 条有向边,要求选出一个环,使得这上面 点权和/边权和 最大. 析:同样转成是01分数规划的形式,F / L 要这个值最大,也就是 G(r) = F - L * r 这个值为0 ...
- (最小生成树)Agri-Net -- POJ -- 1258
链接: http://poj.org/problem?id=1258 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=82831#probl ...
- The First Android App----Adding the Action Bar
In its most basic form, the action bar displays the title for the activity and the app icon on the l ...
- 几个经典的数学库之一学习---VCGlib(1)
1. VCG Libary是Visulization and Computer Graphics Libary(可视化与计算机图形学库)的缩写,是一个开源的C++模板库,用于三角网格和四面体网格的控制 ...
- java递归和反向递归
1. 递归查询树tree结构有两种做法: 第一种,递归查询数据库结构, 第二种,一次性将数据库表中的所有数据查出来,然后再递归查出来的list集合, 第一种做法适合数据量较少的tree结构,因为要一直 ...
- Android-天气预报Demo-JSON数据解析
在上两篇博客,Android-解析JSON数据(JSON对象/JSON数组),Android-Gson解析JSON数据(JSON对象/JSON数组),是介绍了解析本地文件里面的JSON数据: Andr ...
- MVC4 项目开发日志(1)
最近一直在定义一个功能全面,层次结构分明的框架.一边学习一边应用.