3Seven Languages in Seven Weeks

Prolog

逻辑编程

事实与规则统一回溯约束求解

🎯 AI 时代的学习建议:不要只读理论。理解这一章的设计动机(为什么需要这个概念?)和边界条件(什么情况下会失效?)。当 AI 生成的代码涉及这些概念时,你能判断它是否用对了场景。AI 能帮你总结内容,但无法替代你亲手阅读、思考、建立直觉的过程。

第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 = pat

2.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 = 3

2.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 = 1000

2.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 的规则系统实现一个简单的专家系统。


3/7Prol
0%