从基础理论开始学习人工智能(三):盲目搜索——从状态空间图到生成-测试范式

从基础理论开始学习人工智能(三):盲目搜索------从状态空间图到生成-测试范式

系列 :AI 学习笔记 · 从零开始读教材

教材:《人工智能》(第 3 版)第 2 章「盲目搜索」2.0~2.2.3(2.2 生成-测试范式:回溯法、贪心算法、旅行商问题)


一、引言:这一章,我们终于开始"正式搜索"了

前两篇博客里,我们已经两次撞见"搜索"这个词:第 01 篇的 1.3 节「启发式方法」讲它是如何用经验法则提升求解效率的;第 02 篇的 1.5 节「应用和方法」更是把它列为 AI 最古老、最基础的方法骨架。但当时"搜索"更多是个背景词。

从本章开始,教材正式按下"搜索"的开关注册了一批具体算法。第 2 章「盲目搜索」一共讲两组内容:

  1. 问题表示与求解范式 :先用**状态空间图(state-space graph)把问题"画"出来,再用 生成-测试范式(generate-and-test paradigm)直接去找解------其中又演化出 回溯法(backtracking) 贪心算法(greedy algorithm)两种著名的具体策略(2.2.1、2.2.2),并用旅行商问题(TSP)**作为贯穿案例(2.2.3)。
  2. 三种经典的盲目搜索算法:深度优先搜索(DFS)、广度优先搜索(BFS)、迭代加深的深度优先搜索(DFS-ID)------这属于本章 2.3 节,本篇只做预告,下一篇再展开。

本篇学习范围是 2.0 简介 → 2.2.3(旅行商问题),即"先把问题表示清楚、把两种最直白的求解范式吃透",为 2.3 节的系统搜索算法打地基。


二、2.0 简介:智能系统中的搜索

2.0.1 为什么智能系统绕不开"搜索"?

解决人工智能问题的流行方法大致有三类:搜索(search)、知识表示(knowledge representation)与学习(learning),其中搜索是最经典的一支。原因很朴素------

很多"智能"本质上就是"在众多可能中选择正确的那一个"。 从制定旅行路线、规划机器人动作,到解谜题、走棋局,都可以被形式化为:从一个初始状态 出发,通过一系列合法操作,到达某个目标状态。而"如何一步步走过去",就是搜索。

2.0.2 本章算法的全景

本章将介绍的关键算法按层次如下:

层次 内容 定位
问题表示 状态空间图(state-space graph) 把问题建模成"节点 + 边"的图结构
直接求解范式 生成-测试范式(generate-and-test) "先生成、再测试"的朴素思路
改进策略一 回溯法(backtracking) 在部分解上提前止损
改进策略二 贪心算法(greedy) 每步取当前局部最优
典型难题 旅行商问题(TSP) 贪心失效的经典例子,引出分支定界
系统搜索(2.3 预告) DFS / BFS / DFS-ID(盲目搜索) 不使用问题域知识的系统性搜索

三、2.1 状态空间图:把问题"画"出来

3.1 定义:状态空间图是什么

状态空间图(state-space graph)是对问题的一种表示方法。 某个具体问题的解,将对应状态空间图中的一条路径;问题的解通常需要在这个结构中搜索(无论它是树还是图),搜索始于起始节点,止于终点或目标状态。

这句话是本章的"题眼"。它告诉我们三件事:

  1. 问题可以被表示成一张图------图里的每个要素都对应问题的一种可能处境;
  2. "求解"变成"在图上寻路"------从一个起点状态,沿着合法操作一路走到目标状态;
  3. 搜索有起点和终点 ------起点是起始节点(起始状态) ,终点是目标状态(goal state)

3.2 状态空间树的结构

教材先给了状态空间树(state-space tree)的直观结构。它由两部分组成:

  • 节点(node):图中每个椭圆都是一个节点,代表问题的一个状态;
  • 分支 / 弧(arc) :节点之间的弧表示将状态空间树移动到新节点的运算符(operator)(或应用该运算符的结果)。

节点中有两种特殊类型:

节点类型 含义
起始节点(start node) 表示问题的起始状态(start state),搜索从这里出发
目标状态(goal state) 问题预期的终点;搜索进行到此时即可停止

图 13 状态空间树:每个椭圆是一个节点(问题的一个状态),节点间的弧代表运算符(把系统移动到新状态的合法操作);搜索从起始节点(起始状态)出发,沿分支一步步接近目标状态。

状态空间树包含了问题可能出现的所有状态 以及这些状态之间所有可能的转换 。有时我们只要求找到任意一个解 ,有时则要求找到代价最小的解(如最短路径)------那么就需要在搜索时对路径开销进行比较。

顺便记录教材的一个明确定义:解的代价是达到目标状态所需要的运算符的数量(而不是实际搜索所花费的工作量),它更接近"程序运行时间"而非"开发时间"的语义。


3.3 配套案例一:假币问题(12 枚硬币称 3 次)

假币问题(False Coin Problem)是状态空间图最经典的入门案例:

有 12 枚硬币,已知其中一枚是假的(伪造的),但不知道这枚假币比真币轻还是重 。天平可以告诉我们任意两组硬币是否等重、或者哪一组更重。目标是:只允许称 3 次,找出那枚假币。

这里的状态是什么?每一枚硬币都可能"可疑地被选为假币",而天平每一次称量都会把可能性一分为二地收窄。把"当前哪些硬币还有嫌疑"作为状态、把"这一次天平称哪两组"作为运算符,整个问题就被组织成了一棵状态空间树------从"12 枚都有嫌疑"出发,经过 3 层分支,最终收敛到唯一的假币。教材正是用这个例子说明:同一个问题可以建模成状态空间图,求解就是在图中搜索一条通向唯一解(叶子)的路径。

3.4 配套案例二:微型假币问题(6 枚硬币)

为了让结构更清晰,教材给出了微型假币问题(Mini False Coin Problem) :与假币问题完全相同,但只涉及 6 枚硬币

图 14 微型假币问题的状态空间图(参照教材图 2.1 思想):初始时 6 枚硬币 C1 C2 C3 C4 C5 C6 均有嫌疑;第一次天平称量 C1C2 与 C3C4:若不相等,说明假币在 C1 C2 C3 C4 中;若相等,说明假币在 C5 C6 中。每次称量都收缩嫌疑集合,图的路径即通向唯一假币的过程。

把图 14 读作一棵状态空间树:根节点代表"6 枚均有嫌疑"的起始状态,一次称量(运算符)产生两类子状态;继续称量收窄范围,树越往下分叉越少,最终到达"锁定唯一假币"的目标状态。这直观展示了:

  • 括号集合是"状态"------记录当前还有哪些硬币可能造假;
  • 天平称量是"运算符"------把可能性空间切分、缩小;
  • 树的路径就是问题求解的过程------从起点到目标。

同时它也预告了一个贯穿本章的观察:假币问题很像二分法,每次称量都尽量把可能硬币数量砍半;3 次称量之所以能搞定 12 枚,正是因为 2³ = 8...(不,这里要小心:12 枚 × 2 种轻重方向 = 24 种可能,3 次称量有 3³ = 27 种结果组合,略大于 24,所以"称 3 次"在信息论上是可行的)。

小提示:这条"3³ ≥ 24"的论证是信息论视角的自学延伸,教材本节不要求推导,仅帮助理解"为什么 3 次足够"。


四、2.2 生成-测试范式:先生成,再检查

4.1 范式定义

生成-测试范式(generate-and-test paradigm) 是问题求解的一种直接方式:

先给出可能的解,再检查每个可能的解,看是否有候选解能够构成问题的解。

它把求解拆成两个轮流进行的动作:

  1. 生成(Generate):提出一个候选解;
  2. 测试(Test):检验该候选解是否满足所有约束、能否构成真正的解。

如果测试通过,就宣布成功;否则继续生成下一个候选,直到穷尽。

4.2 案例:n 皇后问题

教材用 n 皇后问题来解释这个范式:

将 n 个皇后放置在一个 n×n 的棋盘上,使得任何两个皇后都不互相攻击 ------即任何两个皇后都不占据相同的行、相同的列或相同的对角线 。这些条件被称为问题的约束条件(constraints)

以 4 皇后为例:4 枚棋子放在 4×4 棋盘共 16 个格子里,四皇后总共有 C(16,4) = 1820 种放置方法。借用"生成-测试"的思路,可以这样找解:

  • 生成器每次提出一种放置方案(比如"(第 1 行第 1 列、第 2 行第 3 列、第 3 行第 1 列、第 4 行第 2 列)");
  • 测试器检查这个方案里的任意两个皇后是否同行、同列、同对角线;
  • 通过 → 输出方案;不通过 → 生成器继续给出下一个方案。

图 15 生成-测试范式:先生成候选解,再测试其是否满足所有问题约束;满足则宣布成功并输出,否则循环生成下一个候选。右侧为教材风格的伪代码结构。

4.3 生成器的三属性

既然要"生成所有可能解再逐一测试",生成器(generator)的质量直接决定范式效率。一个好的生成器应当具备三个属性

属性 英文 含义
完备的 complete 给出每个可能的解------不会漏掉任何候选
非冗余的 non-redundant 如果某个解被拒绝,这个解就不会再次被给出(事实上,即使是成功的解也只给出一次)------不做重复劳动
知情的 informed 生成器有一些信息,允许它对给出的解做出一些限制------可以排除不可能的情况

解读:完备 保证"找得到",非冗余 保证"不重来",知情是"用信息剪枝"------一个理想生成器既不死板枚举(完备 + 非冗余),又能利用问题结构迅速缩小候选范围(知情)。这三条属性是后续理解所有搜索策略的标尺。

4.4 生成-测试范式的伪代码

教材给出的伪代码结构如下:

复制代码
{While 没有找到解,但仍有候选方案
    [
      生成可能的解
      测试其是否满足所有的问题约束条件
    ]
 End While}
IF 找到某个解,则宣布成功,并输出此解
Else 宣布没有找到解

翻译成人话:"只要有候选没试完,就不断'生成一个 → 测一下';一旦冒出满足所有约束的解就成功收工;全部试完仍没有,就宣布无解。"


五、2.2.1 回溯法:把"注定失败"的分支提前掐掉

5.1 从完全枚举法说起

在介绍回溯法前,教材先定义了一个反面参照------完全枚举法(exhaustive enumeration)

完全枚举法也是一种搜索方法,它会查看所有情况以寻找问题的解,甚至在已经发现当前步骤不可能成功得到解的情况下,还可能从部分解开始进一步往后搜索。这要求测试者在每一步给出部分解后,都要检查以保证问题的约束条件没有被违反。

也就是说,完全枚举法"一条道走到黑":哪怕已经看出当前 3 个皇后的摆法互相攻击了,它依然会继续把第 4 个皇后放进去试------于是大量注定失败的方案被完整地枚举完毕,白白浪费时间。

5.2 回溯法的改进思路

回溯法(backtracking)是对完全枚举法的一种改进。

针对某个问题,给出解的过程会被分成多个步骤 。回溯法每一步都按规定的方式做出选择,但多了一个关键动作------检查与回退

  • 如果问题的约束条件得到满足 ,那么搜索将进行到下一步
  • 如果任何选择都得不到可行的部分解 ,那么搜索将回溯到前一步,撤销前一步的选择,继续尝试下一个可能的选择。

这正是"部分解"(partial solution,即只解决了问题一部分的解)概念的意义:与其放着显然非法的方案不管,不如在部分解阶段就提前判定其不可行,从而放弃整棵子树。

5.3 用 4 皇后问题理解回溯

以皇后摆放过程为例。假设每一步把一个皇后摆到一个棋格中,并且前面的第 1, 2, ..., i−1 步都成功摆放了皇后,接下来摆第 i 个皇后:

  • 如果第 i 个皇后在任意 棋格中都会违反约束条件(与已摆放的皇后同行 / 同列 / 同对角线),那么必须返回到第 i−1 步,撤销第 i−1 步的选择,换一个位置重新尝试。

图 16 回溯过程示意:第 1 行放第 1 个皇后①;第 2 行试放第 3 列可行②;随后发现第 3 行任意列 都会与已放皇后互相攻击(红色 X),立刻判定该分支无解,于是回溯到上一步,撤销②、把第 2 个皇后换列重摆(②′),再重新尝试第 3 行------比起完全枚举,提前剪掉了大量注定失败的摆法。

对比一下两种做法的差别:

行为 完全枚举法 回溯法
发现部分解已冲突 仍继续把后续皇后放满再整体检查 立即回溯、撤销上一步、换选择
处理被放弃的分支 完整展开 提前剪枝,不再深入
需要的工作量 大(如 4 皇后 1820 种全枚举) 明显更少(提前止损)

一句话总结回溯法:"走一步、验一步;走不通,退回上一步换条路。" 这正是 4.3 节"知情"思想在约束求解中的具体落地。


六、2.2.2 贪心算法:每次都选当下最好的

6.1 定义

贪心算法(greedy algorithm) 是另一种把问题分步求解的经典策略:

贪心算法总是包含一个必须优化(最大化或最小化)的目标函数(objective function) 。先将一个问题分成几个步骤进行求解,其中每次只考虑一个输入,在每一步都选择当下看起来最好 / 最优的选择,从而希望最终得到整体上的最优解。

6.2 三步拆解

  1. 分步求解:把一个问题切分成多个步骤,一次只处理一个输入;
  2. 明确目标函数:每一步的评价都围绕某个目标函数(如"总开销最小""收益最大")展开;
  3. 局部最优决策 :每一步都贪心地取当前状态下的最优选择,不回头、不改判

教材给的贪心形象很准确:它每一步都考虑最优解,以寻求整体上的最优解 ,但它是局部最优策略------只考虑当前状态下的最优,而不考虑整个问题的全局最优。

6.3 贪心的优点与陷阱

图 17 贪心算法示意:把问题分成若干步骤,每一步都只考虑当前输入,选择当下最优(如当前可选边中开销最小者)并锁定;因为每一步都只盯局部,最终未必得到整体最优------这正是贪心的核心取舍。

优点:求解效率很高,思路直白,适合许多结构与"当前最优 = 全局最优"兼容的问题。

陷阱(可能失效)计算机科学中的一些问题是不能用这种范式来求解的。 因为"每一步局部最优"并不总能导向"全局最优"------一个看起来不大的早期决策,可能把后续路径逼入高开销的境地。下一节的旅行商问题就是最经典的"贪心失效"例子。


七、2.2.3 旅行商问题:贪心失效的经典舞台

7.1 问题定义

旅行商问题(Traveling Salesperson Problem,TSP,也称旅行销售员问题) 是组合优化的经典难题:

给定 n 个顶点的加权图 (即每条边上带有开销值),求从某个顶点 Vᵢ 出发,经过加权图中的所有顶点(每个顶点只经过一次) ,然后返回到 Vᵢ 的最短路径 。---或者说,寻找一条开销最小的回路(cycle)

注意两个硬性约束:每个顶点恰好经过一次 (不能遗漏、不能重复);最终要回到出发点(形成回路)。

7.2 案例:一张 5 顶点的加权图

图 18 TSP 的加权图示例:5 个顶点 A--E,边上标注开销。标红示例为回路 A→B→C→D→E→A(总开销 = 各边权之和,图中已标注)。贪心算法按"当前最小边"选择虽然能得到一条回路,但不一定是最优回路

假设我们用贪心算法 求 TSP:从 A 出发,每一步选择"下一个未访问顶点中开销最小"的边走下去。这样的策略很快,但结论令人警醒------在旅行商问题中,贪心算法不一定能找到最佳路径(最优回路):早期贪便宜选择的小边,可能迫使后面走成本高昂的大边,最终总开销反而不如"先让一步、再整体平衡"的路线。这正是 6.3 节所述陷阱的实证。

7.3 分支定界(branch and bound)

那么 TSP 怎么严谨求解?教材引入分支定界算法

分支定界(branch and bound)算法是广度优先搜索的一种变体 。在这种搜索算法中,节点按照开销不减少的原则进行探索,可以成功解决旅行商问题。

三个要点值得记录:

  1. 它是 BFS 的变体------不是逐层盲目铺开,而是基于"开销"来调度探索顺序;
  2. 按开销不减少的顺序探索------总是优先扩展当前累计开销最小的部分路径,相当于"离最优更近的分支先走";
  3. 配合"定界"剪枝------一旦某条部分回路已经超过已知可行解的开销,就整支剪掉,从而有效缩小搜索空间,让 TSP 这类组合爆炸问题变得可求解。("按开销不减少"正是统一代价搜索 / 分支定界的精髓,它保证第一条到达目标的完整回路即为最优。)

这给我们的学习提示很清晰:遇到"贪心会失效"的问题,就要升级到更严谨的搜索策略------用"开销"调度搜索、用"界"剪枝。这也是 2.3 节系统性盲目搜索算法的前奏。


八、本章前五节小结(2.0--2.2.3)

小节 核心概念 一句话总结
2.0 简介 搜索在智能系统中的作用 智能常等于"在可能中做出正确选择",搜索是核心方法之一
2.1 状态空间图 节点 / 分支(弧)/ 起始节点 / 目标状态 把问题表示成图,求解就是在图上从起点走到终点
2.1 案例 假币问题(12 枚 3 次)、微型假币(6 枚) 天平称量收窄嫌疑集合,路径通向唯一假币
2.2 生成-测试 生成候选 → 测试约束 朴素的"先猜再验"范式,例:n 皇后(4 皇后 C(16,4)=1820 种)
2.2 生成器三属性 完备 / 非冗余 / 知情 好生成器:不漏、不重、会用信息剪枝
2.2.1 回溯法 部分解、约束满足前进、冲突回溯 走不通就退回上一步换路,剪掉注定失败的子树
2.2.2 贪心算法 目标函数、分步求解、局部最优 每步取当下最优,希望全局最优------但可能失效
2.2.3 旅行商问题 TSP、回路、分支定界 贪心不保证最优;分支定界按开销不减少探索,可解 TSP

九、总结:一章思维导图

把 2.0~2.2.3 的核心知识点收拢成一张放射状思维导图,方便复习时一眼掌握全貌:

图 19 本章前半部分总结导图。中心主题为「第 2 章 盲目搜索(2.0--2.2.3)」,六个主分支展开:2.0 简介、2.1 状态空间图、2.2 生成-测试范式、2.2.1 回溯法、2.2.2 贪心算法、2.2.3 旅行商问题;底部归纳两条主线:一是在图上从起始节点搜到目标状态,二是从"生成-测试"演进到"回溯 + 贪心"再走向"分支定界"。


十、学习心得与下一步

10.1 学习心得

  1. "状态空间图 = 把问题翻译成图语言" 。以前总觉得"建模"很抽象,2.1 节用假币问题一下就点破了:状态(还有哪些嫌疑)、运算符(称哪两组)、起始节点、目标状态------四件事一对齐,问题就自动变成了一张可以"走"的图。会画状态空间图,才算真正开始做搜索。
  2. 生成-测试是搜索的"最小公约数" 。2.2 的范式虽然朴素,却是后面几乎所有搜索算法的骨架:生成器负责"造候选",测试器负责"验真伪",而效率全部藏在生成器的三属性里(完备、非冗余、知情)。理解了这三条,再回头看"剪枝""回溯""启发式"就都不陌生了------它们本质都是在让生成器"更知情"。
  3. 回溯法给我的启发是"及时止损" 。完全枚举法最大的浪费是:明知不可行还硬把整条路径走完。回溯法引入了"部分解 + 前瞻检查",走一步验一步,走不通立刻退回上一步------"宁可后退一步,也不在错误分支上浪费十步",这是效率思想最直观的一次亮相。
  4. 贪心的教训是"局部最优 ≠ 全局最优" 。TSP 用一句话就击碎了"每步选最小的总没错"的天真:沿着最小边走一圈,总开销反而不如含让路的路线。这提醒我:看到"每次取最优"的算法,第一反应应该是问"它的局部决策会不会伤害整体?" 而分支定界给出的解药------按开销不减少探索 + 用界剪枝------也为后面学习统一代价搜索(UCS)埋下了伏笔。
  5. 信息量的视角很有用。12 枚假币问题 3 次称量为什么可行?因为 24 种可能(12 枚 × 轻重 2 方向)装得进 3³ = 27 种结果;微型假币问题同理。虽然这是自学延伸,但它让我明白了"搜索为什么有上下界",让整章内容一下有了信息论的味道。

10.2 下一步预告

本章还剩 2.3 节------三种真正的盲目搜索算法:DFS、BFS 与 DFS-ID 。它们将回答"状态空间图上到底按什么顺序走"这个更系统的问题,并引入完备性、最优性、时间与空间复杂度四大评价指标。下一篇博客(第 04 篇)将正式进入 2.3 节,把这三兄弟讲透、画透、比透。敬请期待。


参考资料与说明

  • 教材内容与引文出处:《人工智能》(第 3 版)第 2 章「盲目搜索」2.0 简介、2.1 状态空间图(假币问题、微型假币问题)、2.2 生成-测试范式(n 皇后问题、生成器三属性、伪代码)、2.2.1 回溯法、2.2.2 贪心算法、2.2.3 旅行商问题(分支定界)。
  • 数值核对说明:4 皇后在 4×4 棋盘中的组合数为 C(16,4)=1820;12 枚假币问题(24 种可能、3³=27 种结果)"3 次称量可行性"为信息论视角的自学延伸,已标注,非教材原文公式。
  • 本文所有示意图均由 Python 3 + matplotlib 绘制,无任何 AI 生成水印;中文文字均已检查,清晰无乱码、连线不压字。
  • 经典背景知识参考:Russell & Norvig《Artificial Intelligence: A Modern Approach》中关于状态空间搜索、生成-测试、回溯、贪心与分支定界的经典论述,用于对照理解教材原文。
相关推荐
qyz_hr38 分钟前
拥抱AI,红海云筑牢企业组织与人力数据底层能力
人工智能
有梦想的骇客40 分钟前
PyTorch学习笔记
pytorch·笔记·学习
Capricorn19881 小时前
个人知识库接入大模型频现“幻觉引用”?排查 RAG 溯源失效问题,解析知芽构建可信第三大脑的底层架构
大数据·论文阅读·人工智能·笔记·架构·论文笔记
LaughingZhu1 小时前
Product Hunt 每日热榜 | 2026-08-27
人工智能·深度学习·神经网络·搜索引擎·百度
时代分流1 小时前
生成式搜索时代的 GEO 技术体系与落地实践:解析矩擎 GEO 5.0 全栈架构
人工智能
DeepAgent1 小时前
AI Agent 工程实践(35):我的 AI Engineering OS 最终架构
大数据·人工智能·agent
陈年老古董1 小时前
深度学习入门笔记:从神经元到深度神经网络
人工智能·笔记·深度学习·神经网络·学习
ZGIAI2 小时前
ZGI Workflow:外部接口成功后,任务状态怎么落下来
人工智能·架构
ZGIAI2 小时前
ZGI Agent 发布:配置改了,线上为何还是旧版本
人工智能·架构