搜索 —— 啓發式搜索 —— 爬山法

【概述】

爬山法(Hill Climbing,HC)是一種局部擇優的貪心搜索算法,其本質上是梯度下降法。

該算法每次從當前的節點開始,與周圍的鄰接點進行比較:

  • 若當前節點是最大的,那麼返回當前節點,作爲最大值
  • 若當前節點是最小的,就用最高的鄰接點替換當前節點,從而實現向山峯的高處攀爬的目的

如此循環往復,直到達到最高點爲止。

但該算法的主要問題是:局部最大,即某個節點會比周圍任何一個鄰居都高,但只是局部最優解,並非全局最優解。

如下圖,在處於當前解時,爬山法搜索到局部最優解後,就會停止搜索,因爲在局部最優解這個點,無論向哪個方向小幅度的移動,都無法得到更優解

此外,其還存在以下兩種問題:

  • 高地問題:搜索一旦到達高地,就無法確定搜索最佳方向,會產生隨機走動,使得搜索效率降低
  • 山脊問題:搜索可能會在山脊的兩面來回震盪,前進步伐很小

當出現以上問題後,只能隨機重啓爬山算法來解決。

【主要思路】

首先,隨機選擇一個登山的初始時間 T,這個參數是隨機選擇

然後,只要當 T 大於一個邊界值 EPS 時,就將當前點與其鄰接點進行比較:

  • 如果 res<newRes,轉移答案,並記錄新座標點 pos
  • 如果 res>newRes,不轉移

之後,根據記錄下來的新座標點 pos,去轉移狀態,一般爲:sta = sta + (node[pos] - sta) * T;

最後,對 T 乘以一個小於但十分接近於 1 的數 delta,以體現時間對答案的影響。

不斷重複上述步驟,直到鄰接點中不再有比起大的點。

int getPos(double x) {//比較答案並獲取新座標點
    int pos;//新座標點
    double res = -INF;
    for (int i = 1; i <= n; i++) {
        double newRes = getRes(x, node[i]);//獲取新狀態答案
        if (newRes > res) { //比較答案
            res = newRes; //更新結果
            pos = i; //記錄新座標點
        }
    }
    return pos;
}
void HC(double &x,double &y) {
    double T = 1;
    while (T > EPS) {
        int pos = getPos(x);//獲取下一狀態的座標
        sta = sta + (node[pos] - x) * T;//轉移x狀態
        T *= 0.96;
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章