剪枝 + 优化搜索顺序

0/1背包:寻求收益最大值 维护了收益的上界和下界 优先级:优先搜索收益上界更大的状态,更可能获得较大的路径总和 剪枝:剪掉理论上界小于当前维护的最小下界的状态 旅行商问题:寻求总和最小值 维护了路径总和的下界 优先级:优先搜索路径总和下界更小的状态,更可能获得较小的路径总和 剪枝:剪掉理论下界大于当前维护的最小下界的状态

只寻找一个解 vs 寻找全部解 这两类题目对于优先级的要求是不同的,如果是只寻找一个解,当优先级冲裁不正确时,找到的第一个解就不是预期的解,而且找到这个解后也不会再去考虑其他解了,答案就是错误的。如果是寻找全部解,优先级的仲裁并不对影响答案正确性,其只是影响了搜索路径,即使优先级的判断是错误的,但是最终也是从全部解中确定答案,所以正确性不会收到影响。

上界更大和下界更大,哪个才能代表最终答案的可能值更大? 上界更小和下界更小,哪个才能代表最终答案的可能值更小? 这一问题决定了在判断优先级时到底要比较哪一个值,实际的答案是两个值都能够代表这一点。使用哪一个作为优先级判断条件都是可以的(寻找全部解的问题)(实际测试,执行效率不太相同,但是我觉得这个实际运行效率是和输入数据的实际情况强相关的,并不存在理论上的差异)

上界和下界的比较 为何0/1背包问题要维护收益的上界和下界两个值,而旅行商问题就只维护了一个下界 由于0/1背包和旅行商问题都是会搜索到全部解的问题,所以上界和下界对于优先级判定并没有什么太大的影响。 所以只需要考虑二者对于剪枝是否存在影响。

ppt和《陈玉福算法讲义》中给出的0/1背包的解法中,下界是一个可行解,上界是一个估计上限。给出的旅行商问题的解法中,下界是一个估计下限。 旅行商问题目前给定的这种剪枝方式是否是错误的?以及如何验证 0/1背包是求解最大收益, 目前给的策略是:旅行商问题是求解最小回路成本,仅维护一个状态的下界,并且此下界并不是一个可行解。当一个状态的下界大于已知的最下下界时,就将该状态剪掉。我认为状态A的下界小于状态B的下界,并不能确定从状态A得到的解就一定小于从状态B得到的解。因为此下界并非一个确定的可行解,只是一个估计。

一个检测方法是利用0/1背包问题,0/1背包问题是求解最大收益,并且上界也是一个预估值,并非一个可行解。将0/1背包的剪枝策略修改为:当一个状态的上界小于已知的最大上界时,就剪掉该状态。

不难发现以上两个问题是方向相反,但各部分都对应的两个问题。

以下数据如果0/1背包仅使用上界作为剪枝标准是无法得到正确答案的 4个物品,背包容量5 收益:2 4 4 5 重量:1 2 3 4 答案:0 1 1 0 最初计算出上界=8.666667,下界=6;不装入第一个物品时计算出上界=8,下界=8, 如果只根据上界<已知最大上界就剪枝,都不用看其他状态,就第一个物品不装这个状态就直接被剪掉了,但是它实际是答案的路径。 产生这种问题的原因就是上界并非确切值,虽然计算出上界8.66667,但是这个值是根本取不到的,但是8<8.666667就剪枝,就出现了问题。

如果ppt或者讲义给出的旅行商问题的剪枝方法是正确的,那么它计算的下界必须是一个可行解而非仅仅是一个预估值。

剪枝可以剪的不足,但是不能多剪,否则可能会遗漏答案的

剪枝剪掉的应当是那些可以确定得不到最优解的搜索分支,所以要考虑的是当前搜索状态的上界和下界同已维护得到的上界和下界之间满足何种关系时,可以确定当前状态继续搜索下去也一定不会得到最优解,这时候就可以剪掉这一分支。

这一章节的知识递进逻辑 回溯法(dfs)/队列式(bfs) -> 添加简单剪枝(中间过程和已经找到解进行比较)-> 添加复杂剪枝(在上述剪枝基础上,附加根据上下界进行剪枝)-> 通过优先级优化搜索顺序

在实际问题中,优先级的判定往往可以根据上下界就能够确定了。所以解决问题的关键在于两点: 1.描述好一般搜索的过程(这里可以不考虑剪枝的问题,就是纯dfs或bfs) 2.根据问题类型推断需要计算上界还是下界 3.利用上界或下界优化搜索顺序(实际上只是一句话的事,体现在代码上也不过是将原有搜索使用的空间修改为优先队列)

为什么0/1背包给出的上下界计算方式计算出来的就是下界,怎么确定给出的就是下界呢,对于任何一个可行解,怎么就能够确定是>=它而不是<=它?

对于剪枝环节,为什么有些问题只需要维护上下界中的一个,为什么有些问题就必须两个都维护? 一个很简单的例子就是0/1背包和旅行商问题(我们暂且认为旅行商维护的下界就是确定的可行解) 现象:0/1背包同时维护了上界和下界,旅行商则只维护了下界。 结论:需要维护上下界中的哪一个,是问题本身和我们维护的上下界到底是可行解还是预估值有关。 具体解释:首先说明问题本身,假设问题期望求解的是最大值,在剪枝时就应当剪掉那些确定只能得到较小的解的状态;假设问题期望求解的是最小值,在剪枝时就应当剪掉那些确定只能得到较大解的状态。也就是说问题决定了我们剪枝的目标。 由于求解最大值和求解最小值是相似的,这里以求解最大值为例。此时的核心问题是:如何能够确定一个状态只能得到较小的解?答:当我们能够得到一个上界,并且该上界是一个可行解时,具有较小上界的状态得到的解一定小于具有较大上界的状态得到的解,这一点并不难理解。但是这种说法背后蕴含着两个问题:1.如果得到的上界不是一个可行解呢?2.能否通过下界比较来得到我们希望的结论。 首先说明问题1,如果得到的上界不是一个可行解,只是一个预估值,具有较小上界的状态得到的解是否还一定小于具有较大上界的状态得到的解?答案是不一定,预估值和可行解的区别就在于是否是一个状态确定能够取到的,预估值就意味着并不一定取得到这个值,考虑一种极端情况,具有较大上界的状态最终取到的解是较小上界-1,而具有较小上界的状态最终恰好就取到了上界处,这和条件并不冲突。所以说如果得到的上界是一个预估值,我们并没有办法仅通过这一个条件判断出最终解的关系。 然后说明问题2,通过对问题1的分析,不难看出可行解对分析问题的贡献是要大于预估值的,所以这里我们不妨假设两个状态的下界得到的是可行解。即使我们人为地将已知条件增强,但是我们仍然无法根据下界对状态的解做出任何判断。下界更大也并不一定最终的解就更大,下界更小就更得不到什么结论了。 综上所述,当问题期望求解的是最大值时,剪枝就必须依靠上界。最理想的情况就是找到一个是可行解的状态上界,如果无法找到可行解,只能找到预估值,那就只有依靠下界。 按照类似的方式进行推理,当问题期望求解的是最小值时,剪枝就必须依靠下界。最理想的情况就是找到一个是可行解的状态下界,如果无法找到可行解,那就只有依靠上界。 需要注意到,以求解最大值为例,我们说在上界无法找到可行解的时候必须依靠下界进行剪枝,这是考虑这种用上下界进行剪枝时的说法,如果说我们只依靠界限函数和确定的答案值res之间的比较进行剪枝,当上界小于某一个确定的res值时,就剪掉该分支,我们就只需要确定一个上界就可以,此时就不需要使用下界。这两种方式的区别在于使用上下界之间的比较进行剪枝剪掉的要更多,因为上下界考虑的或者说出现的要比确切的答案值更加提前。这是两种不同的剪枝。 将结论带入实际问题判断正确性:0/1背包问题期望求解的是最大值,但是上界是一个预估值,所以就依靠了下界进行剪枝;旅行商问题期望求解的是最小值,不过下界是可行解,所以剪枝就只使用了下界,没有依靠上界。 接下来进一步考虑如果在求最大值时,确实没有找到一个是可行解的上界,所以要依靠下界,这个时候的下界有要求必须是可行解吗?我们有一个现成的例子0/1背包问题就是这种局面,上界是预估值,所以需要引入下界,我们先不管0/1背包问题的下界是可行解还是预估值,先考虑它是如何结合上下界进行剪枝的。当某一个状态的上界小于已知下界的最大值时,就剪掉这个状态。我们考虑在这种判断条件下,如果下界不是可行解判断是否依然有效?答案是有效的,因为上界对应状态的解是<=上界,而下界对应状态的解是>=下界,上界<下界,所以上界对应状态的解<=上界<下界<=下界对应状态的解,这里下界能不能真正取到并不重要。 也就是说我们要么找到属于可行解的所需要的单个界,要么引入另一个界,此时两个界都是可以预估值,只要保证界和真实值之间正确的关系即可。 换言之,如果我们发现不是一定需要的那个界是易求的,我们实际需要的界如果不好求可行解,直接用预估值就行。

此章节一个比较混乱的点 此章节实际涉及到两类问题:求最大值问题 和 求最小值问题。 无论是ppt还是《陈玉福算法讲义》,讲述角度其实都是面对的最小值问题,例如所谓的LC-检索,即最小成本检索,其实说最小成本,这个是无关乎求最大值和最小值的,即使是最大值我们追求的也是最小成本,不过明显的一点区别是,求最小值问题最小成本和目标值的方向是相同的,但是求最大值问题最小成本和目标值方向是相反的,因为求最小值问题数据越小成本对应越小,求最大值问题,数据越大成本越小,所以在求最大值的问题中,只要把成本转换为目标值的负数后,实现上才更加便利。 求最大值问题不妨参考0/1背包问题的写法,只说明何者为上界,何者为下界,何者为优先级函数。在什么条件下可以进行剪枝。 其实我觉得方法核心就在于上下界函数上,解决实际问题并不需要再去考虑什么成本函数,那些只是在理论分析中存在让人感到迷惑。

几种函数的辨析 1.成本函数 2.成本估计函数 3.上下界函数

以上几种函数并非完全无关,或者说完全不同的东西。可能它们的内容是相同的,只不过在不同的问题中,就具有了不同的名称。 上下界函数是用于剪枝环节的,这一阶段只是单纯的要求所找的上下界必须确实是上下界。 成本函数和成本估计函数是用于优化搜索顺序环节的。根据成本函数来调节搜索顺序,能够更快搜索得到答案节点,一般要求估计值<=真实值,即成本估计值<=成本,不过这种说法是对于极小化问题的,因为我们追求成本更小,这刚好符合极小化问题的搜索方向,极大化问题需要修改符号使其的搜索方向与成本相同。

注意剪枝时的条件判断 以0/1背包作为问题引入,当一个状态的上界<已知下界的最小值或上界<=已知答案最小值时,把这一搜索分支砍掉,着重需要理清<和<=这两个判断条件,当一个上界=已知下界的最小值时,可能这一状态是根节点到答案节点路径上的一个点,因为上界和下界都要先于答案被计算出,所以此时的上界和下界可能就是答案值,所以相等的情况不能贸然砍掉。不过此处会考虑一个问题,就是上界和下界是预估值还是可行解对此有影响吗?因为0/1背包确定的上界是预估值,下界是可行解,是因为下界是可行解所以导致了这种问题吗? 其实这里有一个思维上的误区,即预估值一定就是估计值。实际上我们称一个结果是预估值,只是在某些情况下的结果是预估值,如果是答案路径上的节点,计算出来的就都是可行解,也就是说预估值是在某些情况下是预估值,某些情况下就可能是可行解,而可行解就必须所有情况都是可行解。我们不能对预估值做出任何假设。

第五章回溯 -> 第六章 分枝限界 <=> dfs -> 队列bfs -> 优先队列bfs

寻找最小值 -> 成本函数维护下界,限界函数维护最小值 寻找最大值 -> 成本函数维护上界,限界函数维护最大值 (成本/限界函数,虽说是函数,成本函数就是个和状态对应的变量,限界函数是个全局的变量) 所以说 成本函数 和 限界函数 的维护方向是一致的,不过成本函数(准确来说是成本估值函数维护的是非确定值,限界函数往往维护的是确定值(对维护不确定值的正确性仍存疑)) 成本(估计)函数负责调整搜索顺序,限界函数负责剪枝

关于限界函数,成本函数,成本估计函数的选取,从目前来看,均应该和题目需要最值化的数据相吻合。 例如0/1背包问题期望寻求最大收益,限界函数选择的是当前确定得到的解中的最大收益,成本函数应当选择从当前状态能走到的多个解中的最大收益,成本估计函数选取的是收益的上界,也就是说二者维护的都是最大收益,只不过一个是确定值,一个是上界。 旅行商问题期望寻求最小路径长度,限界函数选择的是当前确定得到的解中的最小路径长度,成本函数应当选取从当前状态所能走到的解中的最小路径长度,成本估计函数选取的是路径长度的下界。

以上就是限界函数,成本函数,成本估计函数的联系和区别

概念上的混乱解决了,剩下的难点就是成本估计函数的计算问题了。