为何Prolog中多个print指令会导致所有答案重复?
问题:为何Prolog代码输出出现重复?
知识库
parent(claudia, taiane). parent(wl, cris). parent(cris, jim). parent(cris, pedro). man(jim). man(pedro). man(w). man(wl). woman(taiane). woman(claudia). woman(cris).
无重复的代码示例
当main谓词仅包含一个查询与打印逻辑时:
main:- man(M), print(M), nl, fail. main:- halt.
使用命令 swipl -q -s exercise-family-tree.pl -g main 执行,输出无重复结果,一切正常。
出现重复的代码示例
当在main中增加查询逻辑,使用两个不同变量的打印时:
main:- % 找出数据库中既有父亲又有儿子的女性 woman(X), parent(X, S), parent(F, X), man(F), man(S), print(X), nl, man(M), print(M), nl, fail. main:- halt.
此时执行后所有答案出现重复,疑问:为何第二种情况会导致答案重复?
注:该问题与此前问题无关,请勿提供交互式REPL相关解决方案。
原因分析
问题出在Prolog的回溯机制与查询组合逻辑上:
- 前半段查询
woman(X), parent(X, S), parent(F, X), man(F), man(S)会生成多个独立解:在你的知识库中,符合条件的X只有cris,但cris有两个儿子(jim和pedro),因此该查询会产生两个不同的绑定解:- 解1:
X=cris, S=jim, F=wl - 解2:
X=cris, S=pedro, F=wl
- 解1:
- 每一个
X的解都会触发后续的man(M), print(M), nl, fail逻辑——也就是遍历所有男性实例打印,再通过fail触发回溯。 - 这就导致:第一次处理
X=cris的第一个解时,打印所有男性;回溯到X的查询后,会找到X=cris的第二个解,再次打印所有男性。最终表现为所有男性输出重复一遍,同时cris也被打印两次。
本质是前半段查询存在多解(即使X值相同,但绑定的S变量不同,属于不同的Prolog解),每个解都会完整执行后半段的男性遍历逻辑,因此整体输出出现重复。
内容的提问来源于stack exchange,提问作者John Smith
相关产品推荐
相关产品推荐

