《人工智能现代方法(第4版)》 第6章 约束满足问题 学习笔记

AI的出现,是否能替代IT从业者? 10w+人浏览 1.4k人参与

🎯 本章要解决什么?给各种“填坑”问题找个通用解法

想象以下场景:

  • 教务处老师:排课表(课程不冲突、老师不跑场、教室够用);
  • 宿舍管理员:调宿舍(不打呼噜的在一起、不同班的混住、上下铺分配);
  • 装修队长:买材料(颜色搭配、预算不超、尺寸合适);
  • 数独爱好者:填数字(每行每列每宫1-9不重复);

这些看似不同的问题,其实都是同一类问题: 有一堆“坑”(变量)要填,每个“坑”有可选“土”(值域),填的时候要满足一堆“施工要求”(约束)。

本章教你:如何系统性地“填坑”,而不是靠蒙。


一、CSP是什么?拆解“填坑三要素”

📦 三个核心零件

任何CSP问题都包含这三样:

零件专业术语中国化比喻数独例子
要填的坑变量待决定的事项81个格子
能用的土值域每个坑能填的材料每个格子可填1-9
施工规范约束填坑时必须遵守的规矩行/列/宫不重复

🏗️ 形式化表示(以排课表为例)

变量:{语文课, 数学课, 英语课, 物理课...}
值域:每个课的可选时间 = {周一1-2节, 周一3-4节...}
约束:
    1. 语文老师不能同时上两门课(不同课时间不能相同)
    2. 教室容量要够(课的学生数 ≤ 教室容量)
    3. 体育课不能排在上午第一节(特定值限制)

关键特点

  • 不关心顺序:先排数学还是先排语文,最终结果一样;
  • 只关心最终分配:每个“坑”都填上合适的“土”;
  • 约束可能很复杂:两个变量之间(A≠B),或多个变量之间(A+B+C=10);

二、约束传播:提前排除“肯定填不对的土”

🎯 核心思想:别等到最后才发现矛盾

就像玩扫雷

  • 笨方法:随便点,点到雷就死;
  • 聪明方法:根据数字推算哪些肯定是雷,先插旗;

📐 一致性检查的四个层次

1. 节点一致性(NC):每个坑自己的要求。
“体育课不能排上午第一节”
→ 从体育课的值域里直接删除“周一第1节”

检查:每个变量单独看,值域里的值都满足自己的一元约束。

2. 弧一致性(AC):两个坑之间的互相限制。
“张老师不能同时上语文和数学”
语文课选了“周一1-2节”
→ 数学课的值域里删除“周一1-2节”

检查:对于变量X的每个可能取值,变量Y都至少有一个值能与它配对成功。

AC-3算法(最常用):

def AC_3(所有约束):
    队列 = 所有约束边  # 如(语文课,数学课)
    while 队列非空:
        (X,Y) = 队列.pop()
        if 修订(X的域, 基于Y):  # 删掉X中无法和Y任何值配对的值
            for Z in X的所有邻居:  # 所有和X有约束的变量
                队列.add((Z,X))  # Z可能也要重新检查

生活比喻

  • 你妈:“周末要么去姥姥家,要么去奶奶家”;
  • 你爸:“周末必须去奶奶家”;
  • 弧一致性检查
    • 你的值域{姥姥家,奶奶家};
    • 你爸的值域{奶奶家};
    • 检查:你能选“姥姥家”吗?不能,因为和你爸的“奶奶家”冲突 → 删除“姥姥家”;
    • 结果:你只能选“奶奶家”;
3. 路径一致性(PC):通过第三个坑传递的限制。
A说:“我和B不同班”
B说:“我和C同班”
虽然没有直接约束,但可推出:A和C一定不同班!

检查:对于每对值(Xi,Xj),存在一条路径通过其他变量使得约束都能满足。

4. k一致性:更广义的“连坐检查”
  • 1一致性 = 节点一致性;
  • 2一致性 = 弧一致性;
  • 3一致性 = 路径一致性;
  • k一致性:任意k-1个变量赋值后,第k个变量都能找到兼容值;

三、回溯搜索:系统性地“试错填坑”

🔍 基本回溯:一条路走到黑,不行就回头

def 回溯搜索(当前分配):
    if 所有变量都分配完了:
        return 当前分配
    
    选一个未分配的变量X
    for 每个值 in X的值域:
        if 值满足所有与已分配变量的约束:
            把(X=值)加入当前分配
            结果 = 回溯搜索(当前分配)
            if 结果不是失败:
                return 结果
            从当前分配中移除(X=值)  # 回溯!
    return 失败

比喻:就像走迷宫用手摸着右墙走

  1. 一直往前走;
  2. 碰壁就退回到上一个岔路口;
  3. 换另一条路;
  4. 重复直到出口;

✨ 智能回溯:别傻退,找到“真凶”再退

问题:基本回溯经常“冤枉好人”。
你填数独:
第1步:A格填1
第2步:B格填2
...
第50步:Z格发现无值可填
基本回溯:退到第49步 → 不对 → 退到48步 → ... 一直退到第1步
但实际上,可能第30步的某个选择就错了!
向后看(Backjumping):直接跳到矛盾源头。
发现Z格无值可填时:
检查:Z和哪些已赋值变量有约束?
发现:Z只和P、Q、R三个格有约束
而P、Q、R是在第30步赋值的
→ 直接跳回第30步重试,跳过中间的20步!
约束学习:吃一堑长一智。
第一次尝试:A=1, B=2 → 失败
学习到:(A=1且B=2)是死路
第二次尝试时,看到A=1,就直接不让B=2了

四、变量和值排序:先填哪个坑?先用哪种土?

📊 变量排序:从“最难搞的坑”开始

原则:先填限制最多的变量(最少剩余值启发式)。

排课表时:
- 体育课:只能排下午(值域小)
- 语文课:全天都可排(值域大)
先排体育课!排好了它,其他课的选择就少了。

度启发式:先填涉及约束最多的变量。

数独中:
- 角落的格子:只受2行2列影响(约束少)
- 中间的格子:受2行2列2宫影响(约束多)
先填中间的!

🎨 值排序:先试“最可能成功的土”

原则:先试给邻居留最多选择的值(最少约束值启发式)。

你选宿舍:
- 选1楼:楼上楼下都还能住人
- 选3楼:只有2楼和4楼受影响
先选1楼,给后面同学留更多选择。

五、局部搜索:当“全盘规划”太慢时

🔄 从“一次性填完”到“边改边优化”

适用场景

  • 课表大体可用,但有少量冲突;
  • 数独填完了,但有几处错误;

🎯 最小冲突启发式

def 最小冲突算法():
    随机给所有变量赋值(可能违反约束)
    for 迭代很多次:
        if 所有约束都满足:
            return 解
        
        选一个冲突的变量X  # 比如时间冲突的课
        给X换一个值,使得冲突最少  # 换个时间,让冲突课变少

比喻调解宿舍矛盾

  1. 初始随机分配(A和B打呼噜的住一起了);
  2. 发现冲突:A被B吵得睡不着;
  3. 尝试调整:
    • 把A换到C宿舍:C也打呼噜 → 冲突数不变;
    • 把A换到D宿舍:D不打呼噜 → 冲突减少;
  4. 选择减少冲突最多的调整

优点:特别适合几乎已经解完的问题微调。


六、问题结构:利用“地形”加速求解

🌳 树状结构CSP:有福了!

如果约束关系形成一棵树:

A — B — C — D  # 线性链
而不是:
A — B — C
  \     /
    D         # 有环

好消息:树状CSP可以在O(nd²)时间内解决(n变量,d值域大小) 方法:拓扑排序后,从叶子开始向前或向后传播。

✂️ 割集调整:把环切成树

原问题:A—B—C—A(三角形,有环)
选一个变量作为“牺牲品”:比如固定A=某个值
剩下:B—C(变成链,可快速解)
然后尝试A的其他值...

比喻解连环套

  • 硬解:每个环都试;
  • 聪明:剪断一个环,解开链,再接回去;

🧩 树分解:把大图拆成小树

复杂约束图 → 拆成几个簇
每个簇内部变量多但簇间形成树
分别解每个簇,再组合

七、实战算法选择指南

问题特征推荐算法生活比喻
小规模(<100变量)回溯+约束传播手工排课表,先排限制多的课
约束很紧(值域小)约束传播为主数独最后几个格,用排除法
约束较松(值域大)回溯搜索为主选选修课,很多时间可选
近似解也可接受局部搜索(最小冲突)调宿舍微调,解决个别矛盾
约束关系是树状拓扑排序+前向检查流水线工序安排
有对称性打破对称性(如固定一个值)分配相同教室时,先定一个

🎮 经典案例:数独求解器怎么工作

🧠 人类解法 vs 算法解法

人类:用“这个格子只能填5”、“这行缺3和8”等启发式 算法:把人类启发式形式化

🔢 数独的约束传播

  1. 节点一致性:已知数字的格子,值域固定;
  2. 弧一致性(AC-3)
    格子(1,1)=5
    → 第1行所有其他格子删除5
    → 第1列所有其他格子删除5
    → 左上宫所有其他格子删除5
    
  3. 递归回溯:当传播不动时,选一个格子猜数字。

⚡ 优化技巧

  • MRV:先填可选数字最少的格子;
  • 向前检查:赋值后立即更新邻居的值域;
  • 智能回溯:冲突时直接跳到相关格子;

💡 CSP思维:从“填坑”到“设计坑”

逆向应用:设计容易解的问题

如果你想设计一个好解的数独

  1. 给的初始数字要能充分约束(用约束传播能推到很多格);
  2. 避免需要大量猜测回溯;
  3. 最好有唯一解;

CSP的哲学启示

  1. 约束不是敌人,是向导:约束越紧,搜索空间越小;
  2. 顺序很重要:先处理最难的部分;
  3. 局部冲突可以局部解决:不一定全盘重来;
  4. 结构决定难度:树状问题简单,全连接问题难;

最后一句大实话
生活中很多问题都是CSP:找对象(互相看对眼)、组团队(技能互补)、安排假期(家人时间都合适)。
学会系统性地“填坑”,而不是凭感觉乱试,成功率会高很多。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值