Prolog双重否定问题:为何loves1生效而loves不生效?
为什么Prolog中
loves返回true而loves1返回false? 我们定义爱情需要满足相互喜欢(friendship)且排他(双方都没有喜欢其他人),但示例中loves(kate, tom)返回true,loves1(kate, tom)返回false,核心原因是loves的实现存在语法和逻辑错误,而loves1是符合预期的正确实现。
一、loves1的逻辑(符合预期)
loves1的规则分两步:
- 先确保
X和Y互相喜欢(满足friendship(X,Y)); - 再通过
\+ ((likes(X, Z), Z \= Y); (likes(Y, W), W \= X))判断:不存在X喜欢的非Y对象,也不存在Y喜欢的非X对象。
对应示例数据:
- Kate和Tom互相喜欢,满足
friendship(kate,tom); - 但Kate还喜欢Paul(
likes(kate,paul),且paul\=tom),所以(likes(X,Z), Z\=Y)这个子句成立,外层的\+取反后结果为false,因此loves1(kate,tom)返回false,完全符合“排他”的定义。
二、loves的实现(存在致命错误)
loves规则里的关键判断行完全写错了:
(not_friendship((X,Z), Z\=Y), not_friendship((Y,W), W\=X))
错误1:语法不匹配
not_friendship的定义是接受两个参数not_friendship(X,Y),但这里调用时把(X,Z)作为第一个参数、Z\=Y作为第二个参数,和原定义的参数类型完全不匹配。Prolog会把这些当作全新的结构处理,根本不是你想表达的“X和Z不是朋友且Z≠Y”。
错误2:逻辑完全偏离意图
就算忽略语法问题,这段代码也没有实现“排他”的逻辑。实际执行时:
- 因为没有任何
friendship((X,Z), ...)的事实,所以not_friendship((X,Z), Z\=Y)会返回true; - 同理
not_friendship((Y,W), W\=X)也返回true;
结合前面的friendship(X,Y),整个loves(X,Y)就会返回true——它根本没检查X或Y是否喜欢其他人,只是做了无意义的判断。
修正后的loves实现
如果要让loves符合“相互且排他”的定义,应该改成和loves1一致的逻辑,或者拆分写:
loves(X,Y):- friendship(X,Y), \+ (likes(X,Z), Z\=Y), \+ (likes(Y,W), W\=X).
内容的提问来源于stack exchange,提问作者MickWise
相关产品推荐
相关产品推荐

