SWI-Prolog事实是否具备双向性?新手关于婚姻事实的疑问
关于Prolog中对称关系的处理问题
嘿,这个问题问得特别好——刚接触Prolog的时候很容易对这类关系的处理产生疑问,我来给你掰扯清楚:
首先明确一点:Prolog不会自动推断对称关系。你定义了married(a,b)这个事实,它只会把“a和b已婚”作为已知信息,但不会默认“b和a已婚”也是成立的。如果直接查询?- married(b,a),程序会返回false,除非你明确告诉它这个反向关系。
那怎么解决这个问题呢?有两种常见的方式:
直接添加反向事实:最简单粗暴的办法就是多写一条
married(b,a)。但如果你的事实很多(比如有成百上千条婚姻关系),这种方式就太繁琐了,而且容易出错。定义对称规则(推荐):这是更优雅、可扩展的做法。你可以把基础事实和对称规则分开,比如:
% 存储原始的婚姻事实 married(a, b). % 定义一个对外的谓词,处理对称查询 is_married(X, Y) :- married(X, Y). is_married(X, Y) :- married(Y, X).这样一来,不管你查询
?- is_married(X, b)还是?- is_married(b, X),都会得到正确的结果X = a。而且这个规则可以复用在所有对称关系上,比如friend/2这类关系也可以用同样的逻辑处理。
为什么Prolog不自动做这件事呢?其实很好理解:不是所有关系都是对称的。比如parent(a, b)(a是b的父母),你肯定不希望程序自动推断parent(b, a)成立。所以Prolog把关系的对称性交给程序员来定义,这样更灵活,也符合逻辑编程“明确声明规则”的核心思想。
如果你不想额外定义一个is_married谓词,也可以调整规则避免递归问题,比如:
married(X, Y) :- married(Y, X), X @< Y.
不过这种方式需要额外的比较条件,不如分开谓词清晰,新手还是推荐第一种规则写法。
内容的提问来源于stack exchange,提问作者Julian Garcia
相关产品推荐
相关产品推荐

