You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Prolog动物逻辑谜题:原子唯一约束实现与死循环排查

Prolog狩猎逻辑谜题死循环排查与声明式实现

问题根源

你遇到的不是真正的死循环,是搜索顺序错误导致的组合爆炸:

  • 原代码先枚举所有动物、工具、地点的全量取值,再做去重、再校验单条冒险规则,5个动物/工具/地点的全排列组合总量超过170万,Prolog回溯需要遍历完绝大多数无效组合才能找到解,运行时间极长,看起来就像卡死。
  • 手动编写固定参数个数的all_unique/5不仅可读性差,也没有从根本上解决搜索空间过大的问题。

实现思路

遵循声明式编程“尽早剪枝、约束前置”的原则:

  1. 保留你已经写对的单条冒险校验逻辑(adventure/1、invalid/1、iff/2)完全不需要修改;
  2. 先按固定猎人顺序,逐个匹配符合单条规则的冒险属性,直接剪枝掉所有违反单条规则的取值;
  3. 用permutation/2谓词实现全局唯一性约束:只要保证选出来的动物/工具/地点列表是对应全量集合的一个排列,自然满足“所有原子仅使用一次”的要求,不需要手动写两两不等的判断,可读性更强。

完整可运行代码

% 事实库
hunter(professor).
hunter(doctor).
hunter(colonel).
hunter(fire_chief).
hunter(captain).
animal(rhino).
animal(bison).
animal(puma).
animal(hippo).
animal(elephant).
tool(stick).
tool(empty_gun).
tool(garment).
tool(hands).
tool(stone).
location(north_africa).
location(central_africa).
location(south_africa).
location(west_africa).
location(east_africa).

% 各分类全量值列表,用于全局唯一性校验
all_animals([rhino, bison, puma, hippo, elephant]).
all_tools([stick, empty_gun, garment, hands, stone]).
all_locations([north_africa, central_africa, south_africa, west_africa, east_africa]).

% 双向蕴含工具谓词
iff(A, B) :- A , B ; not(A) , not(B).

% 非法组合规则
invalid_list([
    [doctor, _, _, east_africa],
    [doctor, hippo, _, _],
    [colonel, _, _, central_africa],
    [_, rhino, _, central_africa],
    [_, _, empty_gun, west_africa],
    [_, _, garment, west_africa],
    [_, elephant, stick, _]
]).
invalid(A) :- invalid_list(LL), member(A, LL).

% 单条冒险合法性校验
adventure([H, A, T, L]) :-
    hunter(H),
    animal(A),
    tool(T),
    location(L),
    not( invalid([H, A, T, L]) ),
    iff( H = professor, T = stone),
    iff( H = colonel, A = rhino),
    iff( H = fire_chief, L = south_africa),
    iff( A = bison, L = north_africa),
    iff( T = hands, L = central_africa),
    iff( H = captain, A = puma),
    iff( H = captain, T = empty_gun).

% 排列谓词,若Prolog环境无内置可手动添加
permutation([], []).
permutation(List, [H|T]) :- select(H, List, Rest), permutation(Rest, T).

% 全局求解谓词
solve(Adventures) :-
    % 按猎人固定5条冒险的结构,避免重复排列
    Adventures = [
        [professor, A1, T1, L1],
        [doctor, A2, T2, L2],
        [colonel, A3, T3, L3],
        [fire_chief, A4, T4, L4],
        [captain, A5, T5, L5]
    ],
    % 先校验单条冒险规则,尽早剪枝
    adventure([professor, A1, T1, L1]),
    adventure([doctor, A2, T2, L2]),
    adventure([colonel, A3, T3, L3]),
    adventure([fire_chief, A4, T4, L4]),
    adventure([captain, A5, T5, L5]),
    % 全局唯一性约束:三类属性为对应全量集合的排列
    all_animals(As), permutation([A1,A2,A3,A4,A5], As),
    all_tools(Ts), permutation([T1,T2,T3,T4,T5], Ts),
    all_locations(Ls), permutation([L1,L2,L3,L4,L5], Ls).

运行结果

直接调用求解谓词,可瞬间得到唯一合法解:

?- solve(X).
X = [
    [professor, bison, stone, north_africa],
    [doctor, elephant, hands, central_africa],
    [colonel, rhino, stick, west_africa],
    [fire_chief, hippo, garment, south_africa],
    [captain, puma, empty_gun, east_africa]
] ;
false.

规则校验

解完全符合所有给定规则:

  • 教授用石头攻击野牛,在北非狩猎
  • 医生在中非狩猎,遇到大象,赤手空拳驱离
  • 上校在西非狩猎,遇到犀牛,用棍子驱离
  • 消防长官在南非狩猎,遇到河马,用衣物驱离
  • 船长在东非狩猎,遇到美洲狮,用空枪击中

内容的提问来源于stack exchange,提问作者LearnDude

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 21:30:42