代碼 | 自適應大鄰域搜索系列之(7) - 局部搜索LocalSearch的代碼解析
好了小夥伴們我們又見面了,咳咳沒錯還是我。不知道你萌接連被這麽多篇代碼文章刷屏是什麽感受,不過,酸爽歸酸爽。今天咱們依然講代碼哈~不過今天講的依然很簡單,關於局部搜索LocalSearch的代碼。
01 總體概述
其實,LocalSearch在本算法中不是必須使用的,用戶可以根據需要來選擇是否啟用這個功能。但是一般情況下,有了LocalSearch以後效果會好一點。而且本著服務讀者的態度(我可以不用,但是小編你不能不講),就講講這個模塊吧。和之前講的幾個模塊差不多,具體代碼也是分成兩個部分進行實現的:
- LocalSearch的定義
- LocalSearch的管理
LocalSearch的定義用了一個很簡單的抽象類ILocalSearch用來提供接口的、而LocalSearch的管理用了ILocalSearchManager、SimpleLocalSearchManager兩個類,其中ILocalSearchManager也是抽象類,而SimpleLocalSearchManager則是繼承於ILocalSearchManager並實現了相應的接口。下面對他們進行一一講解。
02 ILocalSearch
其實這個類只提供了兩個純虛函數作為接口,也是簡單得不能再簡單了,performLocalSearch用以執行一次LocalSearch操作,getName返回該LocalSearch的名字。
```C++
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開始信號,在啟動整個算法的時候起到協調作用。 ```C++ 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。
```C++
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就不需要講解了吧~
```C++
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的代碼解析