代码 | 自适应大邻域搜索系列之(7) - 局部搜索LocalSearch的代码解析
前言
好了小伙伴们我们又见面了,咳咳没错还是我。不知道你萌接连被这么多篇代码文章刷屏是什么感受,不过,酸爽归酸爽。今天咱们依然讲代码哈~不过今天讲的依然很简单,关于局部搜索LocalSearch的代码。
01 总体概述
其实,LocalSearch在本算法中不是必须使用的,用户可以根据需要来选择是否启用这个功能。但是一般情况下,有了LocalSearch以后效果会好一点。而且本着服务读者的态度(我可以不用,但是小编你不能不讲),就讲讲这个模块吧。和之前讲的几个模块差不多,具体代码也是分成两个部分进行实现的:
- LocalSearch的定义
- LocalSearch的管理
LocalSearch的定义用了一个很简单的抽象类ILocalSearch用来提供接口的、而LocalSearch的管理用了ILocalSearchManager、SimpleLocalSearchManager两个类,其中ILocalSearchManager也是抽象类,而SimpleLocalSearchManager则是继承于ILocalSearchManager并实现了相应的接口。下面对他们进行一一讲解。
02 ILocalSearch
其实这个类只提供了两个纯虚函数作为接口,也是简单得不能再简单了,performLocalSearch用以执行一次LocalSearch操作,getName返回该LocalSearch的名字。
class ILocalSearch
{
public:
//! Perform a local search on the solution.
//! \return true if the solution is improved.
virtual bool performLocalSearch(ISolution& sol)=0;
//! \return the name of the local search operator.
virtual std::string getName()=0;
};
03 ILocalSearchManager
这个抽象类也非常简单,只有两个接口。useLocalSearch用以判断是否要使用LocalSearch,而startSignal开始信号,在启动整个算法的时候起到协调作用。
class ILocalSearchManager
{
public:
//! \param sol the solution to be improved.
//! \param status the status of the alns iteration.
//! \return true if the solution has been improved.
virtual bool useLocalSearch(ISolution& sol, ALNS_Iteration_Status& status)=0;
//! Indicate that the optimization process starts.
virtual void startSignal()=0;
};
04 SimpleLocalSearchManager
SimpleLocalSearchManager对LocalSearch进行了一定的扩充,加入了addLocalSearchOperator的操作,用以添加LocalSearch。值得注意的是,该LocalSearchManager管理的可以是多个LocalSearch。
class SimpleLocalSearchManager: public ILocalSearchManager {
public:
SimpleLocalSearchManager(ALNS_Parameters& parameters){param = ¶meters;};
virtual ~SimpleLocalSearchManager(){};
//! \param sol the solution to be improved.
//! \param status the status of the alns iteration.
//! \return true if the solution has been improved.
virtual bool useLocalSearch(ISolution& sol, ALNS_Iteration_Status& status);
//! Add a local search operator to the manager.
void addLocalSearchOperator(ILocalSearch& ls);
virtual void startSignal(){};
private:
//! A vector containing the local search operators managed by the current instance.
std::vector<ILocalSearch*> localSearchOperators;
//! Parameters of the ALNS.
ALNS_Parameters* param;
};
useLocalSearch和addLocalSearchOperator具体实现代码如下,相信对迭代搜索了解的同学,对下面的过程那是熟悉得不能再熟悉了,特别是improvement 变量的复位操作(如果有改进,那么接着搜索下去,直到最大迭代次数为止,如果没有改进就不搜索了。)addLocalSearchOperator就不需要讲解了吧~
bool SimpleLocalSearchManager::useLocalSearch(ISolution& sol, ALNS_Iteration_Status& status)
{
if(status.getNewBestSolution()!=ALNS_Iteration_Status::TRUE
|| status.getAcceptedAsCurrentSolution()!=ALNS_Iteration_Status::UNKNOWN)
{
return false;
}
else
{
status.setLocalSearchUsed(ALNS_Iteration_Status::TRUE);
bool improvement;
do
{
improvement = false;
for(size_t i = 0; i < localSearchOperators.size(); i++)
{
improvement = localSearchOperators[i]->performLocalSearch(sol)||improvement;
}
}while(improvement);
if(improvement)
{
status.setImproveByLocalSearch(ALNS_Iteration_Status::TRUE);
return true;
}
else
{
status.setImproveByLocalSearch(ALNS_Iteration_Status::FALSE);
return false;
}
}
}
void SimpleLocalSearchManager::addLocalSearchOperator(ILocalSearch& ls)
{
//TODO find out why the set.find() == set.end() does not work.
bool ok = true;
for(size_t i=0; i< param->getForbidenLsOperators().size() && ok; i++)
{
if(param->getForbidenLsOperators()[i] == ls.getName())
{
std::cout << "NO " << ls.getName() << std::endl;
ok = false;
}
}
if(ok)
{
localSearchOperators.push_back(&ls);
}
}
05 小结
差不多到此整个ALNS框架已经讲得差不多了,相信大家在看了这么多代码以后,心里早已经有了一个数了。下面几篇推文将为大家展现一个实例,怎么在该框架的基础上定制自己的代码求解相应的问题。为了演示,还是给大家实例一个TSP问题的求解过程哈。谢谢!
最后做个小小说明:整个系列所有的代码在 代码 | 自适应大邻域搜索系列之(1) - 使用ALNS代码框架求解TSP问题 这篇文章中都能找到代码文件。
代码 | 自适应大邻域搜索系列之(7) - 局部搜索LocalSearch的代码解析的更多相关文章
- 代码 | 自适应大邻域搜索系列之(2) - ALNS算法主逻辑结构解析
00 前言 在上一篇推文中,教大家利用了ALNS的lib库求解了一个TSP问题作为实例.不知道你萌把代码跑起来了没有.那么,今天咱们再接再厉.跑完代码以后,小编再给大家深入讲解具体的代码内容.大家快去 ...
- 代码 | 自适应大邻域搜索系列之(5) - ALNS_Iteration_Status和ALNS_Parameters的代码解析
前言 上一篇推文说了,后面的代码难度直线下降,各位小伙伴可以放去n的100次方心了.今天讲讲一些细枝末节,就是前面一直有提到的参数和一些状态的记录代码.这个简单啦,小编也不作过多解释了.大家直接看代码 ...
- 代码 | 自适应大邻域搜索系列之(3) - Destroy和Repair方法代码实现解析
前言 上一篇文章中我们具体解剖了ALNS类的具体代码实现过程,不过也留下了很多大坑.接下来的文章基本都是"填坑"了,把各个模块一一展现解析给大家.不过碍于文章篇幅等原因呢,也不会每 ...
- 代码 | 自适应大邻域搜索系列之(4) - Solution定义和管理的代码实现解析
前言 上一篇讲解了destroy和repair方法的具体实现代码,好多读者都在喊酸爽和得劲儿--今天这篇就讲点简单的,关于solution的定义和管理的代码实现,让大家回回神吧--哈哈. 01 总体概 ...
- 代码 | 自适应大邻域搜索系列之(6) - 判断接受准则SimulatedAnnealing的代码解析
前言 前面三篇文章对大家来说应该很简单吧?不过轻松了这么久,今天再来看点刺激的.关于判断接受准则的代码.其实,判断接受准则有很多种,效果也因代码而异.今天介绍的是模拟退火的判断接受准则.那么,相关的原 ...
- ElasticSearch 2 (15) - 深入搜索系列之多字段搜索
ElasticSearch 2 (15) - 深入搜索系列之多字段搜索 摘要 查询很少是简单的一句话匹配(one-clause match)查询.很多时候,我们需要用相同或不同的字符串查询1个或多个字 ...
- ElasticSearch 2 (13) - 深入搜索系列之结构化搜索
ElasticSearch 2 (13) - 深入搜索系列之结构化搜索 摘要 结构化查询指的是查询那些具有内在结构的数据,比如日期.时间.数字都是结构化的.它们都有精确的格式,我们可以对这些数据进行逻 ...
- 自适应大邻域搜索代码系列之(1) - 使用ALNS代码框架求解TSP问题
前言 上次出了邻域搜索的各种概念科普,尤其是LNS和ALNS的具体过程更是描述得一清二楚.不知道你萌都懂了吗?小编相信大家早就get到啦.不过有个别不愿意透露姓名的热心网友表示上次没有代码,遂不过瘾啊 ...
- 干货 | 自适应大邻域搜索(Adaptive Large Neighborhood Search)入门到精通超详细解析-概念篇
01 首先来区分几个概念 关于neighborhood serach,这里有好多种衍生和变种出来的胡里花俏的算法.大家在上网搜索的过程中可能看到什么Large Neighborhood Serach, ...
随机推荐
- Scala 算法案例
移除第一个负数之后的所有负数 // 构建数组 val a = ArrayBuffer[Int]() a += (1, 2, 3, 4, 5, -1, -3, -5, -9) // 每发现一个第一个负数 ...
- js复制内容到粘贴板
点击右边内容:<span onclick="copyContent(this);" title="点击复制">啊,我被复制了</span> ...
- 使用Dockerfile构建镜像并push到私有仓库
环境:OS X 10.10.5 maven 3.3.9 Docker version 1.12.2 docker-machine version 0.8.2 程序示例为http://www.cnblo ...
- C#数字日期转成中文日期
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Cons ...
- java对日开发常用语(词汇)总结
日语 英语 中文 备注 並び順(ならびじゅん) order by 排序 項目(こうもく) field 字段,域 ...
- django.http.request中HttpRequest对象的一些属性与方法
HttpRequest对象的属性 属性 描述 path 表示提交请求页面完整地址的字符串,不包括域名,如 "/music/bands/the_beatles/". method 表 ...
- CocoaPods - 发布自己的模块(公有库、私有库)
CocoaPods发布框架到远程公有库 1.编写代码~上传远程仓库 git init git add . git commit -m '提交到本地分支' //关联远程仓库 git remote add ...
- java读取文件的几种方式性能比较
//普通输入流读取文件内容 public static long checksumInputStream(Path filename) { try(InputStream in= Files.newI ...
- 如何避免Linux操作系统客户端登陆超时-linux命令之TMOUT=
工作中经常遇到使用ssh,telnet工具登陆Linux操作系统时,出现的超时问题,怎么处理呢? 添加下面命令: TMOUNT=
- ORACLE获取年初年末,月初月末,季度初季度末
转自:https://www.cnblogs.com/leqhome/p/5319984.html --年初,年末select trunc(sysdate,'yyyy') from dual;sele ...