如何简洁编写Prolog中的传递性谓词gt_?
优化Prolog中传递性谓词的实现
原代码与问题
原代码通过枚举所有可能的间接路径实现了带传递性的大小判断谓词gt_:
gt(ace,ten). gt(ten,king). gt(king,queen). gt(queen,jack). gt_(X,Y) :- ( gt(X,Z1), gt(Z1,Z2), gt(Z2,Z3), gt(Z3,Y) ) ; ( gt(X,Z1), gt(Z1,Z2), gt(Z2,Y) ) ; ( gt(X,Z1), gt(Z1,Y) ) ; gt(X,Y) .
其中gt表示“大于”,本应具备传递性(例如查询gt_(ace, jack)应返回true),但这种枚举路径的写法冗余,新增节点时需要手动修改谓词,扩展性极差。
简洁实现方案
利用递归实现传递闭包,无需手动枚举路径:
% 直接大于的基础情况 gt_(X, Y) :- gt(X, Y). % 间接大于的递归情况:X大于Z,且Z(直接/间接)大于Y gt_(X, Y) :- gt(X, Z), gt_(Z, Y).
实现说明
- 第一个子句处理直接的大小关系,对应原代码的最后一条规则;
- 第二个子句通过递归处理所有间接传递的情况:只要存在中间节点
Z,使得X直接大于Z,且Z通过gt_(即直接或间接)大于Y,则gt_(X,Y)成立。
该实现会自动利用Prolog的回溯机制遍历所有可能的传递路径,比如查询gt_(ace, jack)时,会依次匹配ace>ten→ten>king→king>queen→queen>jack,最终返回true。后续新增卡牌大小关系时,无需修改gt_谓词即可正常使用。
内容的提问来源于stack exchange,提问作者Raffael
相关产品推荐
相关产品推荐

