代码 | 自适应大邻域搜索系列之(4) - Solution定义和管理的代码实现解析
前言
上一篇讲解了destroy和repair方法的具体实现代码,好多读者都在喊酸爽和得劲儿……今天这篇就讲点简单的,关于solution的定义和管理的代码实现,让大家回回神吧……哈哈。
01 总体概述
总所周知的是,每一个算法的最终目标都是求解出一个合理的满足心意的solution。因此对solution的定义和管理基本是每个算法都要涉及的。在本ALNS代码中呢,也对solution进行了一定的抽象和规范化,提供了一些标准化的接口,同样需要在具体使用中去重写这些接口。
关于solution的处理方式总得来说也由两个模块组成:
- 关于solution的定义:ISolution抽象类
- 关于bestSolution的管理:IBestSolutionManager(抽象类)、SimpleBestSolutionManager(派生类)
下面也对其一一进行讲解。
02 ISolution抽象类
该类只是对solution的进行一定的抽象定义,并没有具体实现各个接口,需要coder在后续的使用中重写编写这些接口。它应该具备的功能看代码就能理解了,注释也写得很详细。主要包括几个功能:获取目标值、获取目标惩罚值、解是否可行、获取每个solution独一无二的hash值等。
具体代码也很简单:
class ISolution
{
public:
virtual ~ISolution(){};
//! A getter for the value of the objective function.
//! \return the value of the objective function of this solution.
virtual double getObjectiveValue()=0;
//! \return a penalized version of the objective value if the solution
//! is infeasible.
virtual double getPenalizedObjectiveValue()=0;
//! A getter for the feasibility of the current solution.
//! \return true if the solution is feasible, false otherwise.
virtual bool isFeasible()=0;
//! A comparator.
//! \return true if this solution is "better" than the solution it is compared to.
virtual bool operator<(ISolution&)=0;
//! Compute the "distance" between solution.
//! This feature can be used as part of the ALNS to favor the
//! diversification process. If you do not plan to use this feature
//! just implement a method returning 0.
virtual int distance(ISolution&)=0;
//! This method create a copy of the solution.
virtual ISolution* getCopy()=0;
//! Compute a hash key of the solution.
virtual long long getHash()=0;
};
03 bestSolution的管理
关于bestSolution的管理有两个类搞定,它们的关系如下:
3.1 IBestSolutionManager
IBestSolutionManager其实也是一个抽象类,它也只是起到提供接口的作用。其中isNewBestSolution(ISolution& sol)是判断sol是不是新的最优解。reloadBestSolution(ISolution* currSol, ALNS_Iteration_Status& status)则根据需要判断是否要将已知的最优解作为当前解。
class IBestSolutionManager
{
public:
//! This method evaluate if a solution is a new best solution, and adds it to the
//! best solution pool in this case.
//! \param sol the solution to be tested.
//! \return true if the solution is a new best solution, false otherwise.
virtual bool isNewBestSolution(ISolution& sol)=0;
//! Return a pointer to a best solution.
virtual std::list<ISolution*>::iterator begin()=0;
//! Return a pointer to a best solution.
virtual std::list<ISolution*>::iterator end()=0;
//! This function take care of reloading the best known
//! solution, as the current solution, if needed.
//! \param currSol a pointer to the current solution.
//! \param status the status of the current iteration.
//! \return a pointer to the current solution.
virtual ISolution* reloadBestSolution(ISolution* currSol, ALNS_Iteration_Status& status)=0;
};
3.2 SimpleBestSolutionManager
SimpleBestSolutionManager是继承于IBestSolutionManager的,值得注意的是,它管理的不止是一个BestSolution,而是多个BestSolution的集合(这些BestSolution目标值相同,但是结构不同)。下面是.h文件的代码:
class SimpleBestSolutionManager: public IBestSolutionManager {
public:
SimpleBestSolutionManager(ALNS_Parameters& param);
virtual ~SimpleBestSolutionManager();
virtual bool isNewBestSolution(ISolution& sol);
//! Return a pointer to a best solution.
std::list<ISolution*>::iterator begin(){return bestSols.begin();};
//! Return a pointer to a best solution.
std::list<ISolution*>::iterator end(){return bestSols.end();};
//! This function take care of reloading the best known
//! solution, as the current solution, if needed.
//! \param currSol a pointer to the current solution.
//! \param status the status of the current iteration.
//! \return a pointer to the current solution.
virtual ISolution* reloadBestSolution(ISolution* currSol, ALNS_Iteration_Status& status);
//! Simple getter.
std::list<ISolution*>& getBestSols(){return bestSols;};
private:
std::list<ISolution*> bestSols;
ALNS_Parameters* parameters;
};
再回过头来看看.cpp文件的实现代码,也很简单,讲讲两个函数的实现方式就好了。isNewBestSolution(ISolution& sol)做的可不只是简单判断这么简单:
如果sol和最优解集合中的某个相同,那么返回false。
如果sol的目标值>最优解集合中的解的目标值,返回false。
如果sol的目标值<最优解集合中的某个解的目标值,那么将该最优解从集合中移除。
最后如果没有返回false,将sol加入最优解集合。
而reloadBestSolution(ISolution* currSol, ALNS_Iteration_Status& status)根据status的状态,返回最优解集合中最后一个解或者返回当前解。
bool SimpleBestSolutionManager::isNewBestSolution(ISolution& sol)
{
for(list<ISolution*>::iterator it = bestSols.begin(); it != bestSols.end(); it++)
{
ISolution& currentSol = *(*it);
if(currentSol<sol)
{
return false;
}
else if(sol<currentSol)
{
delete *it;
it = bestSols.erase(it);
if(it == bestSols.end())
{
break;
}
}
else if(currentSol.getHash() == sol.getHash())
{
return false;
}
}
ISolution* copy = sol.getCopy();
bestSols.push_back(copy);
return true;
}
ISolution* SimpleBestSolutionManager::reloadBestSolution(ISolution* currSol, ALNS_Iteration_Status& status)
{
if(status.getNbIterationWithoutImprovementSinceLastReload() > 0 &&
((status.getNbIterationWithoutImprovementSinceLastReload() % parameters->getReloadFrequency()) == 0))
{
status.setNbIterationWithoutImprovementSinceLastReload(0);
delete currSol;
return bestSols.back()->getCopy();
}
else
{
return currSol;
}
}
04 小结
好了,以上就是今天的内容,是不是特别简单呢?相信在克服之前两篇文章的读者来说,后面都是一马平川、一帆风顺了。哈哈。
代码 | 自适应大邻域搜索系列之(4) - Solution定义和管理的代码实现解析的更多相关文章
- 代码 | 自适应大邻域搜索系列之(6) - 判断接受准则SimulatedAnnealing的代码解析
前言 前面三篇文章对大家来说应该很简单吧?不过轻松了这么久,今天再来看点刺激的.关于判断接受准则的代码.其实,判断接受准则有很多种,效果也因代码而异.今天介绍的是模拟退火的判断接受准则.那么,相关的原 ...
- 代码 | 自适应大邻域搜索系列之(7) - 局部搜索LocalSearch的代码解析
前言 好了小伙伴们我们又见面了,咳咳没错还是我.不知道你萌接连被这么多篇代码文章刷屏是什么感受,不过,酸爽归酸爽.今天咱们依然讲代码哈~不过今天讲的依然很简单,关于局部搜索LocalSearch的代码 ...
- 代码 | 自适应大邻域搜索系列之(3) - Destroy和Repair方法代码实现解析
前言 上一篇文章中我们具体解剖了ALNS类的具体代码实现过程,不过也留下了很多大坑.接下来的文章基本都是"填坑"了,把各个模块一一展现解析给大家.不过碍于文章篇幅等原因呢,也不会每 ...
- 代码 | 自适应大邻域搜索系列之(2) - ALNS算法主逻辑结构解析
00 前言 在上一篇推文中,教大家利用了ALNS的lib库求解了一个TSP问题作为实例.不知道你萌把代码跑起来了没有.那么,今天咱们再接再厉.跑完代码以后,小编再给大家深入讲解具体的代码内容.大家快去 ...
- 代码 | 自适应大邻域搜索系列之(5) - ALNS_Iteration_Status和ALNS_Parameters的代码解析
前言 上一篇推文说了,后面的代码难度直线下降,各位小伙伴可以放去n的100次方心了.今天讲讲一些细枝末节,就是前面一直有提到的参数和一些状态的记录代码.这个简单啦,小编也不作过多解释了.大家直接看代码 ...
- 自适应大邻域搜索代码系列之(1) - 使用ALNS代码框架求解TSP问题
前言 上次出了邻域搜索的各种概念科普,尤其是LNS和ALNS的具体过程更是描述得一清二楚.不知道你萌都懂了吗?小编相信大家早就get到啦.不过有个别不愿意透露姓名的热心网友表示上次没有代码,遂不过瘾啊 ...
- 干货 | 自适应大邻域搜索(Adaptive Large Neighborhood Search)入门到精通超详细解析-概念篇
01 首先来区分几个概念 关于neighborhood serach,这里有好多种衍生和变种出来的胡里花俏的算法.大家在上网搜索的过程中可能看到什么Large Neighborhood Serach, ...
- 大数据学习系列之九---- Hive整合Spark和HBase以及相关测试
前言 在之前的大数据学习系列之七 ----- Hadoop+Spark+Zookeeper+HBase+Hive集群搭建 中介绍了集群的环境搭建,但是在使用hive进行数据查询的时候会非常的慢,因为h ...
- 大数据小白系列——HDFS(2)
这里是大数据小白系列,这是本系列的第二篇,介绍一下HDFS中SecondaryNameNode.单点失败(SPOF).以及高可用(HA)等概念. 上一篇我们说到了大数据.分布式存储,以及HDFS中的一 ...
随机推荐
- Linux基石【第二篇】虚拟网络三种连接方式(转载)
在虚拟机上安装完Centos系统后,开始配置静态IP,以方便在本宿主机上可以访问虚拟机,在曲折的配置中,了解到虚拟机还有三种连接方式:Bridged,NAT和Host-only,于是,我又一轮新的各种 ...
- fbx模型动画提取教程附带一个用代码提取的方法
角色已经人形化(Humanoid)了,那它的动画可以用在其它的模型上了也就是可以共用一套模型动画了但是你有没有发现那动画是和fbx模型绑在一起的,没关系你可以选中这几个动画文件按Contrl+D就可以 ...
- $_SERVER['PHP_AUTH_USER']
PHP 的 HTTP 认证机制仅在 PHP 以 Apache 模块方式运行时才有效,因此该功能不适用于 CGI 版本.在 Apache 模块的 PHP 脚本中,可以用 header() 函数来向客户端 ...
- 35-Python - 去除list中的空字符
https://www.cnblogs.com/yspass/p/9434366.html list1 = ['122', '2333', '3444', '', '', None] a = list ...
- Zookeeper 源码(六)Leader-Follower-Observer
Zookeeper 源码(六)Leader-Follower-Observer 上一节介绍了 Leader 选举的全过程,本节讲解一下 Leader-Follower-Observer 服务器的三种角 ...
- Python里seed()函数
seed()函数的功功能是每次改变随机数生成器的种子,会改变下一次随机数模块生成的随机数.seed()方法在每次调用随机函数之前使用. 如果种子不变,那么随机函数生成的随机数相同,例如: #!/usr ...
- 使用windows server2012时FileZilla客户端连接时报150 Opening data channel for directory listing of "/" 响应:425 Can't open data connection
425 Can't open data connection 和 读取目录列表失败 问题解决 这个问题主要是由于使用Passive Mode模式造成的,解决这个问题很简单: 1.在ftp服务软件中设置 ...
- python多版本共存问题
1.环境变量配置,pip路径别忘记加入,否则pip不好使. 2.如果改名python.exe为其他名字,复制一份保留,否则pip容易无法启动进程 参见爆栈: http://stackoverflow. ...
- spring aop记录用户的操作
1.命名空间 xmlns:aop="http://www.springframework.org/schema/aop" http://www.springframework.or ...
- Oracle学习笔记(八)
十一.子查询 1.子查询概述 学习子查询的原因 事例:查询工资比SCOTT高的员工信息 思路:1.scott的工资 select sal from emp where ename='SCOTT'; 2 ...