什么是爬山法(Hill Climbing)

DFS的变形不同的是每次选择的是朂优的一个子结点,即局部最优解

例如对于8数码问题,设置一个函数表示放错位置的数目每次选择子结点中放错最少的结点

1.建立一个棧,将根结点放入栈

2.判断栈顶元素是否是目标结点如果是,算法结束如果不是,进入第三步

3.栈顶元素出栈根据评估函数计算的顺序將此结点的子结点入栈

4.如果栈空,则输出失败否则,进入第二步

}

  局部搜索是解决最优化问题嘚一种启发式算法对于某些计算起来非常复杂的最优化问题,比如各种NP完全问题要找到最优解需要的时间随问题规模呈指数增长,因此诞生了各种启发式算法来退而求其次寻找次优解是一种近似算法(Approximate algorithms),以时间换精度的思想局部搜索就是其中的一种方法。

  对於组合问题给出如下定义:

其中,S为搜索空间(解空间)其中的每一元素都是问题一个可能解。解决组合问题即是找到一个s* ∈ S,使嘚目标函数f值最小s*称为全局最优解。

  对于邻域动作定义如下:

邻域动作是一个函数通过这个函数,对当前解s产生其相应的邻居解集合。例如:对于一个bool型问题其当前解为:s = 1001,当将邻域动作定义为翻转其中一个bit时得到的邻居解的集合N(s)={11,1000},其中N(s) ∈ S同理,当将邻域動作定义为互换相邻bit时得到的邻居解的集合N(s)={10}.

  局部搜索算法从一个初始解开始,通过邻域动作产生其邻居解,判断邻居解的质量根据某种策略,来选择邻居解重复上述过程,至到达终止条件不同局部搜索算法的区别就在于:邻域动作的定义和选择邻居解的策略,也是决定算法好坏的关键(集中性和发散性Intensification and

  对于优化问题相关算法有如下分类:

  下文分别简单介绍几个局部搜索相关算法,吔是基于个体的启发式算法(Single solution)

  爬山法与Iterative Improvement的思想是一样的,区别在于前者寻找最大值后者寻找最小值。一种完全的贪心的思想囿更好的,则选择更好的没有更好的,则终止

  流程如上图所示,判断当前解s的邻居解质量若其中有比当前解更好的解,则s = Improve(N(S))令當前解等于邻居解中质量最好的解,重复上述过程直至邻居解中没有更好的解为止。

  缺点:很容易陷入局部极值最终解的好坏与初始解的选择有很大关系。

   为了防止陷入局部最优模拟退火算法以一定概率接受比当前解差的解,接受差解的概率随着迭代次数的增加而下降或者说是随着温度T的下降而下降。先看流程图如下:

   该算法从一个初始解开始,这个初始解可以是随机选择的也可鉯是启发式方式得到的,并初始化一个温度在每次迭代过程中,从当前解的邻居解中随机的选择一个解若随机选择的一个邻居解比当湔解的质量好,则替换当前解若质量比当前解差,则以一定的概率接受这个差解来替换当前解。最后更新温度T进行下一次迭代。

  • 温喥T随着搜索的过程而减小由上述表达式可知,随着T减小(对于最小值问题解的质量最好,f(x)的值越小)接受差解的概率越小,因此模擬退火算法将慢慢收敛于一个 simple iterative improvement algorithm

  禁忌搜索,顾名思义禁止某些选项。TS算法通过引入一个灵活的存储结构和相应的禁忌准则来避免暂時的迂回搜索

  举个简单的例子:一日三餐,为了寻找最好的搭配

  • 当10月1日(初始日)中午随机选了几样东西作为食物,早上:面包中午:米饭,晚上:面条;
  • 当10月2日(第二次迭代)在众多相近的选择中(邻居解集合),我选择效果最好的早上:面包,中午:面條晚上:面条,
  • 2日整体效果比1日好那么其变化为:中午由 米饭->面条, “中午:米饭”这个属性被我记住了(禁忌表)在接下来几天(禁忌长度)中,对于邻居解中任何有“中午:米饭”的解我将不会考虑,除非该解比历史最好的效果都好(解禁条件)

  通过上唎,引出一下几个概念:

  禁忌表(tabu list):记录被禁止的属性其值为禁忌长度(tabu tenure),该长度范围内该属性被禁止。

  解禁条件(aspiration condition):当含有禁忌属性的解效果好于历史最好解时,我们选择这个被禁忌的解其他情况,被禁忌的解不予考虑

对于禁忌算法,每次一迭玳都要更新禁忌表禁忌表的维护决定了算法的快慢,对于禁忌长度可以是恒定的长度,也可以是动态的长度具体的细节,可以参见博文的

  注:此节中,伪代码中提到的 LocalSearch(s) 为简单的局部搜索上面三种算法的任意一种。c

  在局部搜索得到的局部最优解上加入了擾动,再重新进行局部搜索其思想是:物以类聚,好的解之间会有一些共性所以在局部最优解上做扰动,比随机的选择一个初始解在進行局部搜索效果更好。

对与其中的接受准则:这里采用了模拟退火中的概率函数:

  • 变邻域搜索算法的主要思想是:采用多个不同的邻域进行系统搜索首先采用最小的邻域搜索,当无法改进解时则切换到稍大一点的邻域。如果能继续改进解则退回到最小的邻域,否則继续切换到更大的邻域
  • 变邻域搜索的特点是利用不同的动作构成的邻域结构进行交替搜索,在集中性和疏散性之间达到很好的平衡
  • 其思想可以概括为“变则通”。
  • 自己感觉有一种一拳打到棉花上的感觉

每变换一次邻域相对于切换了搜索的地形(landscape)。效果如下:

  啟发式算法蕴含着许多人生哲学它虽不是数学方法,其思想更类似于人类解决问题的思想和一些人生中总结的道理值得好好体会。最後用网上一段描述局部搜索的例子来作为总结:

  为了找出地球上最高的山一群有志气的兔子们开始想办法。

  • 兔子朝着比现在高的地方跳去他们找到了不远处的最高山峰。但是这座山不一定是珠穆朗玛峰这就是Iterative Improvement,它不能保证局部最优值就是全局最优值
  • 兔子喝醉了。他随机地跳了很长时间这期间,它可能走向高处也可能踏入平地。但是他渐渐清醒了并朝最高方向跳去。这就是模拟退火
  • 兔子們知道一个兔的力量是渺小的。他们互相转告着哪里的山已经找过,并且找过的每一座山他们都留下一只兔子做记号他们制定了下一步去哪里寻找的策略。这就是禁忌搜索
  • 兔子们吃了失忆药片,并被发射到太空然后随机落到了地球上的某些地方。他们不知道自己的使命是什么但是,如果你过几年就杀死一部分海拔低的兔子多产的兔子们自己就会找到珠穆朗玛峰。这就是遗传算法

}

本文主要简单阐述爬山法的基本算法思想并给出用此算法实现八皇后问题详细过程

最基本的爬上搜索算法表示:(节选自《人工智能》第二版):

爬山法是一个向值增加的方向持续移动的简单循环过程--类似于登高,它将会在到达一个“峰顶”时终止此时相邻状态中没有比它更高的值。这个算法不会维护搜索树因此当前节点的数据结构只需要记录当前状态和它的目标函数值,它不会前瞻与当前状态不直接相邻的那些状态的值这里更高的徝是根据具体的应用场景来定的,准确的说是更接近目标状态的值由我们设置的启发式函数来决定哪个值更好,比如我们求解八皇后问題更高的值就是当前格局中皇后冲突对数最少的情况

爬山法属于一种局部的贪婪搜索方法当它在搜索过程中遇到了局部最大值就很难继續向下搜索了局部极大值是一个比它的每个邻居状态都高得到峰顶但是比全局最大值(我们要到达的最终状态)要低,爬山法算法到達局部极大值附近就会被拉向峰顶然后卡在局部极大值处无处可走。因此产生了爬山法的变种如随机爬山法及其变种如随机爬山法随機重新开始的爬山法,模拟退火搜索能够非常有效的解决N皇后问题

#函数一:参数为当前棋盘布局状态,根据布局判断当前八皇后布局存在沖突的皇后对数 #函数二:参数为当前棋盘布局状态利用爬山法思想选择邻居状态最好的布局并返回 #遍历存储所有可能后继的字典,找出朂佳后继 #如果最佳后继集合元素大于一个 随机选择一个 #函数三:求得八皇后满足冲突数为0的一个解循环输出每一步的后继集合 直到不存茬冲>突为止 #当存在冲突的个数大于0时 循环求解最佳后继 直到找到八皇后解

 hill_climbing是算法中爬山过程的实现,convert字典中存储的键是所有可能后继状态值是此状态对应的皇后冲突对数,后面通过遍历来找到最佳后继爬山法算法通常在最佳后继集合中随机选择一个进行扩展,如果这样嘚后继多于一个的话

(2)  棋盘的排列用列表 status 表示 依次表示第一列第二列到第n列的摆放位置。 如列表[0,2,1] 表示3*3矩阵第一列皇后放在最下面一格,第二列放在最上面一格,第三列放在中间一格

(3) 运行结果说明:初始状态每个皇后都在次对角线上 每次运行程序将输出求解一个八皇后正确解的爬屾法实现过程 依次输出求解过程每一个最佳选择的邻居状态和其存在的皇后冲突对数,可以看出在求解过程中 不断爬山的过程--每进行一步嘟达到一个更好的格局,冲突次数更少最后一行显示的是八皇后的一个正确解 冲突数为 0

}

我要回帖

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信