Prolog中规则嵌套使用错误排查及指定动作实现对象查询需求咨询
问题分析与修复方案
你写的规则出问题的核心原因很明确:rel1(Z, L1)这一步完全匹配不到任何事实。因为rel1的第二个参数要求是单个对象(比如'Human'),但你传入的L1是一个列表(比如['Human', 'Machine']),Prolog根本找不到符合rel1(_, [_,_])的事实,所以L2永远是空列表,最终拼接出来的结果自然和你要的不一样。
先理清楚需求逻辑
你要的是所有直接或间接具备指定动作的对象:
- 直接具备:对象本身和动作通过
rel2关联(比如rel2('Human', 'Run')) - 间接具备:对象属于某个类别(通过
rel1的层级链),而这个类别(或者上层类别)具备该动作(比如'Hunter'是'Human'的子类,'Human'能跑,所以'Hunter'也能跑)
正确的实现方式
我们可以先写一个辅助谓词has_action(Object, Action),用来判断某个对象是否直接/间接拥有指定动作:
% 情况1:对象直接关联动作 has_action(Object, Action) :- rel2(Object, Action). % 情况2:对象属于某个父类,父类(递归)拥有该动作 has_action(Object, Action) :- rel1(Object, Parent), has_action(Parent, Action).
然后用findall收集所有符合条件的对象,就是你要的provides_action:
provides_action(Action, ObjectList) :- findall(Object, has_action(Object, Action), ObjectList).
测试验证
现在跑你的查询:
- 执行
?- provides_action('Run', X).
结果会是X = ['Human', 'Machine', 'Hunter', 'Robot', 'WallE'],完全符合你的预期:Human、Machine直接能跑Hunter继承Human的跑能力,Robot继承Machine的跑能力,WallE又继承Robot的跑能力
- 执行
?- provides_action('Kill', X).
按照你的事实,Robot直接关联Kill,WallE继承Robot的Kill能力,所以结果会是X = ['Robot', 'WallE']。如果你的预期是只有WallE,那可能是你对rel2('Robot', 'Kill')的定义有偏差?比如是不是想表达只有WallE能Kill,而Robot本身不能?那调整对应的事实就行,规则逻辑是没问题的。
内容的提问来源于stack exchange,提问作者user86002
相关产品推荐
相关产品推荐

