第3章:Prolog(逻辑编程)
一、导读
1.1 本章学习目标
第3章介绍 Prolog——一门完全不同的编程范式:逻辑编程。在 Prolog 中,你不告诉计算机"怎么做",而是告诉它"是什么",然后让引擎通过逻辑推理找到答案。
本章的核心学习目标包括:
- 理解逻辑编程范式:声明事实、定义规则、提出查询
- 掌握 Prolog 的统一(Unification)机制
- 理解回溯(Backtracking)搜索
- 学会用 Prolog 解决约束求解问题
1.2 为什么本章如此重要
Prolog 展示了编程的第三种范式(继命令式和函数式之后)。在 AI、自然语言处理、专家系统等领域,逻辑编程有独特的优势。理解 Prolog 能拓展你的编程思维——不是所有问题都需要用循环和条件来解决。
1.3 核心问题引导
逻辑编程和命令式编程有什么本质区别?
什么是统一(Unification)?它和模式匹配有什么关系?
回溯搜索是如何工作的?它在什么情况下会失败?
Prolog 适合解决什么类型的问题?
二、核心概念详解
2.1 事实与规则
prolog
% 事实
parent(tom, bob).
parent(tom, liz).
parent(bob, ann).
parent(bob, pat).
% 规则
grandparent(X, Z) :- parent(X, Y), parent(Y, Z).
sibling(X, Y) :- parent(P, X), parent(P, Y), X \= Y.
% 查询
% ?- grandparent(tom, ann). % true
% ?- grandparent(tom, X). % X = ann; X = pat2.2 统一(Unification)
prolog
% 统一是 Prolog 的核心机制
% ?- X = hello. % X 绑定为 hello
% ?- [H|T] = [1,2,3]. % H = 1, T = [2,3]
% 模式匹配
length2([], 0).
length2([_|T], N) :- length2(T, N1), N is N1 + 1.
% ?- length2([a,b,c], N). % N = 32.3 回溯
prolog
% 旅行商问题的简单版本
city(denver).
city(seattle).
city(miami).
distance(denver, seattle, 1000).
distance(seattle, miami, 3000).
distance(denver, miami, 2000).
% 找到所有城市对及其距离
route(A, B, D) :- distance(A, B, D).
route(A, B, D) :- distance(B, A, D).
% ?- route(X, Y, D), D < 1500.
% X = denver, Y = seattle, D = 1000
% X = seattle, Y = denver, D = 10002.4 列表操作
prolog
% 成员检查
my_member(X, [X|_]).
my_member(X, [_|T]) :- my_member(X, T).
% 追加
my_append([], L, L).
my_append([H|T], L, [H|R]) :- my_append(T, L, R).
% 反转
my_reverse([], []).
my_reverse([H|T], R) :- my_reverse(T, RT), my_append(RT, [H], R).
% ?- my_reverse([1,2,3], R). % R = [3,2,1]三、实战案例
3.1 案例一:数独求解器
prolog
% 简单的数独约束
valid_row(Row) :- permutation([1,2,3,4,5,6,7,8,9], Row).
% 检查所有行
valid_rows([]).
valid_rows([Row|Rest]) :- valid_row(Row), valid_rows(Rest).
% 转置矩阵(检查列)
transpose([], []).
transpose([[F|Fs]|Rest], [[F|RFs]|TRest]) :-
transpose(Rest, TRest),
first_elements(Rest, RFs),
% ... 简化版3.2 案例二:家族关系推理
prolog
male(tom).
male(bob).
male(jim).
female(liz).
female(ann).
female(pat).
parent(tom, bob).
parent(tom, liz).
parent(bob, ann).
parent(bob, pat).
parent(liz, jim).
father(X, Y) :- parent(X, Y), male(X).
mother(X, Y) :- parent(X, Y), female(X).
ancestor(X, Y) :- parent(X, Y).
ancestor(X, Y) :- parent(X, Z), ancestor(Z, Y).
% ?- ancestor(tom, jim). % true (tom -> liz -> jim)
% ?- ancestor(X, ann). % X = bob; X = tom四、本章小结
逻辑编程:声明事实和规则,通过查询获取答案。
统一:Prolog 的核心机制,将变量绑定到值。
回溯:自动尝试所有可能的解,失败时回退。
适用场景:约束求解、知识推理、自然语言处理。
五、思考与练习
逻辑编程适合解决什么类型的问题?不适合解决什么问题?
Prolog 的回溯搜索和正则表达式的回溯有什么相似之处?
用 Prolog 的规则系统实现一个简单的专家系统。