【问题标题】:Prolog Query DuplicatesProlog 查询重复
【发布时间】:2018-08-02 02:58:53
【问题描述】:

我已经看到了一些关于这个主题的问题,但是没有一个能真正正确地回答我的问题。我会写一个小例子,这里有一些事实:

football(john).
football(sam).

tennis(john).
tennis(pete).

netball(sandy).

我想创建一条规则,说明 pete 喜欢任何踢足球或网球的人。

likes(pete, X) :- (football(X) ; tennis(X)), X \= pete.

但很明显,当我在 Prolog 中查询它时,john 会出现两次,因为john 既踢足球又踢网球。我希望它只出现一次john。我该如何修改我的代码来做到这一点?

提前致谢 - 丹

【问题讨论】:

  • 唯一真正的方法是使用setof/3。这是因为 Prolog 不会在解决方案之间保持状态,所以它实际上不知道它之前已经给了你一次 john ——除非你使用像 setof/3 这样的二阶谓词让它保持跟踪。

标签: prolog prolog-setof prolog-tabling


【解决方案1】:

一个干净的解决方案是使用 Prolog 系统的 tableing 机制。

例如,在 SWI-Prolog 中,您可以通过在顶部添加以下指令来做到这一点:

:- 表喜欢/2。

使用这个指令,你会得到:

?- 喜欢(皮特,X)。 X = 约翰; X = 山姆。

如果没有它,你会得到:

?- 喜欢(皮特,X)。 X = 约翰; X = 山姆; X = 约翰。

制表也称为SLG分辨率

【讨论】:

  • 问题中的代码有一个微不足道但难以发现的错误(x vs X),这显然是无意的,并且混淆了问题。我冒昧地修改了你的代码,好吗?
【解决方案2】:

这是@DanielLyons 在他对您的问题的评论中提到的方法。

它基于,因此可以跨不同的 Prolog 系统移植。

使用 SICStus Prolog 4.5.0:

| ?- setof(t, likes(pete,X), _).
X = john ? ;
X = sam ? ;
no

【讨论】:

    【解决方案3】:

    SWI-Prolog 提供库(solution_sequences)

    likes(pete, X) :- distinct( ((football(X) ; tennis(X)), X \= pete) ).
    
    ?- likes(pete, X).
    X = john ;
    X = sam ;
    false.
    

    它建立在使表格可用的基础架构之上,坚固耐用,因此它对内存存储有类似的要求。

    【讨论】:

      猜你喜欢
      • 2013-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多