⏱️ 预计阅读时间:60-75分钟
🎯 学习目标:学会怎么解决需要满足多个条件的问题,怎么在对抗环境中选最优策略
📚 核心结论(塔尖)
想象一下,你想解决复杂的搜索问题,比如要同时满足多个条件的拼图,或者跟对手对抗的博弈。这时候简单的搜索方法往往太慢或者根本处理不了。
高级搜索策略解决这两类问题的核心思路是:
- 约束满足 通过回溯搜索和约束传播提前发现冲突,减少需要搜索的范围,就像解数独时先排除不可能的数字,以及需要得同时满足行、列、宫三个条件;
- 博弈搜索通过极小极大算法和剪枝(传统方法,适合可能走法不多的问题)或随机模拟(现代方法,适合可能走法太多的问题)来评估决策,就像下棋时你不仅要考虑自己的走法,还要考虑对手会怎么应对,选一个即使对手反击也能赢的走法。
怎么选方法?看问题特点:
- 约束满足适合需要同时满足多个条件的问题,
- 传统博弈搜索适合可能走法不多、能精确评估的问题(如国际象棋),
- 现代博弈搜索适合可能走法太多、无法精确评估的问题(如围棋)。
那么,怎么通过约束传播提前发现冲突?怎么从对手角度考虑最优策略?当可能走法太多、无法精确评估时,怎么评估决策?这些正是本文要解决的核心。
一、约束满足:通过约束传播提前发现冲突
想象一下,你在解数独。如果每个格子都一个个试数字,试错了再回头,这样太慢了。约束传播的核心思路是:在试之前,先看看哪些数字根本不可能填,提前排除掉,这样就不用试了。比如某个格子想填5,但这一行已经有5了,那就提前排除5,不用再试了。这样能减少需要搜索的范围,就像提前把不可能的路堵死,只走可能的路。具体有两个逻辑:
- 前向检验就像你填一个格子时,顺便看看这个选择会不会让后面的格子填不了,如果会,就提前排除这个选择。
- 弧一致性更强,不仅看当前会不会冲突,还看未来可能的所有冲突,就像不仅看这一步,还看后面几步会不会有问题。当然,检查得越仔细,计算也越慢,需要在效率和强度之间权衡。
优化搜索顺序也能显著提高效率。想象一下,你在解数独,有很多格子要填。先填哪个格子?先填哪个数字?选对了顺序,效率能提高很多。
先填哪个格子? 优先填可能数字最少的格子(MRV,最小剩余值),比如某个格子只能填2或3,那就先填它,因为试两次就知道了。或者优先填受限制最多的格子(度启发式),比如某个格子受行、列、宫三个条件限制,那就先填它,因为限制多,能填的数字少。这样能减少搜索分支,就像先解决最容易确定的问题。
先填哪个数字? 选一个不会限制其他格子太多选择的数字(最少约束值),比如某个格子可以填3、5、7,但填3会让其他格子更难填,那就先试5或7,这样能保留更多选择空间,避免过早卡住。
二、博弈搜索:从对手角度考虑最优策略
想象一下,你在下棋。你走一步,对手走一步,你们轮流下。你的目标是赢,对手的目标也是赢。所以,你不能只考虑自己怎么走最好,还要考虑对手会怎么应对。博弈搜索的核心就是:站在对手的角度,想他会怎么走,然后选一个即使对手应对得最好,你也能赢的走法。
传统方法(α-β剪枝)适合可能走法不多、能精确评估的问题(如国际象棋),现代方法(MCTS)适合可能走法太多、无法精确评估的问题(如围棋)。
传统方法:α-β剪枝
想象一下,你在下棋,想算到终局。你可以把所有可能的对局画成一棵树:你走一步(MAX层),对手走一步(MIN层),你们交替下。极小极大算法的思路是:你选让对手最不利的走法(MAX选最大值),对手选让你最不利的走法(MIN选最小值)。但完全搜索这棵树通常不可行,因为走法太多了,需要优化。
α-β剪枝的核心思路是:在搜索过程中,维护两个值:α(你已经找到的最好结果,你的下界)和β(对手已经找到的最好结果,对手的上界)。当你发现α≥β时,说明对手不会让你得到更好的结果,那就不用再搜索这个分支了,直接剪掉,就像知道这条路走不通,就不用再试了。这样可以显著减少搜索节点数,少算很多步。
为什么α≥β时可以剪枝?想象一下,你在搜索一个分支,已经知道:
- α=5(你已经找到的最好结果,比如你赢了5分)
- β=3(对手已经找到的最好结果,比如对手最多让你赢3分)
既然你已经找到了5分,继续搜索这个分支就没有意义了,因为对手不会让你得到比5分更好的结果。所以可以直接剪掉,不用再试了。这样可以显著减少搜索节点数,少算很多步。
继续想象一个场景:
你在下棋,但不可能算到终局,因为走法太多了。那怎么办?只能限制搜索深度,比如只往前看5步,然后用评估函数评估当前局面的好坏,就像看这5步后,你的棋子位置、对手的棋子位置,判断谁更有利。
评估函数的质量直接影响搜索质量,就像你评估局面的准确性直接影响你的下棋水平。这种方法适合可能走法不多、能精确评估的问题(如国际象棋)。
现代方法:MCTS(蒙特卡洛树)
想象一下,你在下围棋。围棋的走法太多了,每一步都有几百种可能,根本不可能像国际象棋那样算到终局,也不可能精确评估当前局面。那怎么办?蒙特卡洛方法 的思路是:既然不能精确计算,就多试几次,随机下完这盘棋,看哪种走法胜率高。就像你不知道哪个选择好,就每个都试100次,看哪个赢得多。
MCTS(蒙特卡洛树搜索) 通过四个步骤的循环,逐步构建搜索树并评估每个走法:
- 选择:从当前局面出发,沿着搜索树往下走,选一个最有希望的走法继续探索,直到找到一个还没试过的走法。
- 扩展:创建一个新节点,尝试这个还没试过的走法。
- 模拟:从这个新节点开始,随机下完这盘棋,直到游戏结束,看谁赢了。
- 反向更新:把这次模拟的结果(赢了还是输了)沿着路径往回传,更新路径上所有节点的统计信息,比如这个走法试了几次,赢了几次。
UCB/UCT算法的核心是自动权衡"探索"和"利用"。
当你在下棋时,有些走法你已经试过了,知道胜率很高;有些走法你还没试过,不知道好不好。UCB算法会给你一个评分,评分 = 胜率 + 不确定性。胜率高的走法,评分高(利用);没试过的走法,不确定性高,评分也高(探索)。这样,算法既会多试胜率高的走法,也会试试新的走法,避免错过更好的选择。
具体来说,UCB评分 = 胜率(W/N,赢的次数除以试的次数)+ 不确定性(C·√(ln(T)/N),试得越少,不确定性越高)。就像你看到一个走法,虽然只试了1次,但赢了,胜率是100%,不确定性也很高,所以评分很高,值得再试试。另一个走法试了100次,赢了60次,胜率是60%,但不确定性很低,所以评分可能不如那个只试了1次的。这样就能自动平衡:既要多试胜率高的,也要探索新的可能性。
三、方法选择:根据问题特点权衡
没有完美的算法,只有适合不同场景的算法。核心就是在"找全解"、“找得快”、"计算资源"之间找到平衡点。就像你时间紧,就选快的方法;你要求高,就选准确的方法。
想象一下,你在解数独。约束传播可以提前排除不可能的数字,不用再试了,效率很高。但检查得越仔细,计算也越慢。比如你只检查当前格子,计算快但排除得少;你检查所有相关格子,排除得多但计算慢,所以需要在效率和强度之间权衡。
想象一下,你在下国际象棋。传统博弈搜索(α-β剪枝)能精确评估每个局面的好坏,比如你的棋子位置、对手的棋子位置,判断谁更有利。但这种方法需要精确的评估函数,而且只能处理可能走法不多的问题。如果像围棋那样,每一步都有几百种可能,走法太多,无法精确评估,传统方法就处理不了了。
想象一下,你在下围棋。现代博弈搜索(MCTS)通过随机模拟,多试几次,看哪种走法胜率高。但试得越多,越准确,时间也越长。你需要设置模拟次数、UCB参数、时间限制等,在准确性和效率之间平衡。比如你只试100次,速度快但可能不够准确;你试10000次,准确但时间太长。
1488

被折叠的 条评论
为什么被折叠?



