1. 程式人生 > >代碼 | 自適應大鄰域搜索系列之(7) - 局部搜索LocalSearch的代碼解析

代碼 | 自適應大鄰域搜索系列之(7) - 局部搜索LocalSearch的代碼解析

param perf 算法 ear sig 最大 cep return tac

前言

好了小夥伴們我們又見面了,咳咳沒錯還是我。不知道你萌接連被這麽多篇代碼文章刷屏是什麽感受,不過,酸爽歸酸爽。今天咱們依然講代碼哈~不過今天講的依然很簡單,關於局部搜索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 = &parameters;};

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的代碼解析