如何不显示相同的结果是否多次出现-Prolog

如何不显示相同的结果是否多次出现-Prolog,prolog,swi-prolog,Prolog,Swi Prolog,情景 我的代码如下。我的问题是,如何避免多次显示相同的结果 male(charles). male(andrew). male(edward). female(ann). age(charles, 70). age(ann, 65). age(andrew, 60). age(edward, 55). nextking(X) :- age(X,P), age(Y,Q), P>=Q, X\==Y; age(X,55). 电流输出 我需要什么 我需要的

情景

我的代码如下。我的问题是,如何避免多次显示相同的结果

male(charles).
male(andrew).
male(edward).

female(ann).

age(charles, 70).
age(ann, 65).
age(andrew, 60).
age(edward, 55). 

nextking(X) :- age(X,P), age(Y,Q),
               P>=Q, X\==Y;  age(X,55).
电流输出

我需要什么


我需要的输出是查尔斯,安,安德鲁,爱德华。不重复名称。

对于较新版本,您可以使用库:

或者使用经典的“所有解决方案”内置:

?- setof(K,K^nextking(K),Ks),member(X,Ks).
Ks = [andrew, ann, charles, edward],
X = andrew ;
Ks = [andrew, ann, charles, edward],
X = ann ;
...

但在本例中,我们将取消知识库定义的答案顺序。

对于较新版本,您可以使用库:

或者使用经典的“所有解决方案”内置:

?- setof(K,K^nextking(K),Ks),member(X,Ks).
Ks = [andrew, ann, charles, edward],
X = andrew ;
Ks = [andrew, ann, charles, edward],
X = ann ;
...
但是在本例中,我们失去了由KB定义的答案顺序。

您的nextking/1谓词效率很低,而且不能保证按年龄对人员进行排序

例如,如果我们将查尔斯排在事实列表的最后,我们得到:

?- nextking(X).
X = ann ; 
X = ann ;
X = andrew ;
X = charles ;
X = charles ;
X = charles ;
X = edward.
基本上,您编写的te谓词有两个子句:

nextking(X) :-
    age(X,P),
    age(Y,Q),
    P >= Q,
    X\==Y.
nextking(X) :-
    age(X, 55).
第一个简单地将产生任何X,其中存在一个更年轻的人Y。但这并不能保证这些元素被排序。最后,最后一个谓词将与55岁的所有人X统一。对于这个特定的案例,这是可行的,但这意味着如果我们陈述另一个事实,14岁的路易斯,那么这将失败。这种方法不仅不正确,而且即使是正确的,也会非常不稳定

我们可以使用谓词,它不仅执行唯一性过滤器,而且还对元素进行排序

由于我们想按年龄递减对皇室成员进行排序,因此我们应该构造2元组或其他结构来封装这两个参数,其中第一个参数包含负年龄,第二个参数包含对应的人

然后,我们可以使用在单个统一中展开列表:

nextking(X) :-
    setof((NA, X), A^(age(X, A), NA is -A), Royals),
    member((_, X), Royals).
这将生成元素列表,如:

?- nextking(X).
X = charles ;
X = ann ;
X = andrew ;
X = edward. 
不管事实在源文件中是如何排序的。

您的nextking/1谓词效率很低,而且不能保证按年龄对人进行排序

例如,如果我们将查尔斯排在事实列表的最后,我们得到:

?- nextking(X).
X = ann ; 
X = ann ;
X = andrew ;
X = charles ;
X = charles ;
X = charles ;
X = edward.
基本上,您编写的te谓词有两个子句:

nextking(X) :-
    age(X,P),
    age(Y,Q),
    P >= Q,
    X\==Y.
nextking(X) :-
    age(X, 55).
第一个简单地将产生任何X,其中存在一个更年轻的人Y。但这并不能保证这些元素被排序。最后,最后一个谓词将与55岁的所有人X统一。对于这个特定的案例,这是可行的,但这意味着如果我们陈述另一个事实,14岁的路易斯,那么这将失败。这种方法不仅不正确,而且即使是正确的,也会非常不稳定

我们可以使用谓词,它不仅执行唯一性过滤器,而且还对元素进行排序

由于我们想按年龄递减对皇室成员进行排序,因此我们应该构造2元组或其他结构来封装这两个参数,其中第一个参数包含负年龄,第二个参数包含对应的人

然后,我们可以使用在单个统一中展开列表:

nextking(X) :-
    setof((NA, X), A^(age(X, A), NA is -A), Royals),
    member((_, X), Royals).
这将生成元素列表,如:

?- nextking(X).
X = charles ;
X = ann ;
X = andrew ;
X = edward. 

无论事实在源文件中的顺序如何。

我更新了我的问题,提供了有关我的要求的更多详细信息。不确定这是否可行,似乎distinct生成的输出已经与您所需的订单匹配,不是吗?不。当我使用distinctnextkingX时,它只打印出一个名称。这不是我需要的。它应该按年龄的降序显示所有的名字。这就是Prolog的工作原理。。。每次显示一个答案,按;为了得到更多。这是合理的,因为您想用所有解决方案做什么仍然是未知的。如果您对列表满意,只需使用findall:?-findallX,distinctnextkingX,L.或多或少地包装查询即可。。。它保存了返回答案的缓存。但是细节可能很复杂,因为术语可能包含变量……我更新了我的问题,提供了关于我的需求的更多细节。不确定这是否可行,似乎distinct生成的输出已经与您所需的订单匹配,不是吗?不。当我使用distinctnextkingX时,它只打印出一个名称。这不是我需要的。它应该按年龄的降序显示所有的名字。这就是Prolog的工作原理。。。每次显示一个答案,按;为了得到更多。这是合理的,因为您想用所有解决方案做什么仍然是未知的。如果您对列表满意,只需使用findall:?-findallX,distinctnextkingX,L.或多或少地包装查询即可。。。它保存了返回答案的缓存。但是细节可能很复杂,因为术语可能包含变量……你的意思是我将规则更改为nextkingX:-ageX,\ux?对于那个种情况,若我改变事实的顺序,我将不会得到正确的结果。我需要查询以年龄降序显示姓名。我不太懂代码。无论如何,我得到的答案也不正确。我以爱德华的身份得到了答案,查尔斯
,安,安德鲁。正确的答案应该是查尔斯、安、安德鲁、爱德华,因为这是年龄递减的正确顺序。我不太理解代码。这段代码是你写的还是来自其他地方?简单地说,一个人成为下一任国王的条件是什么?该法典暗示下一任国王是55岁或至少比其他人年长的任何人。基于现有的数据,可能是任何人。我自己编写的代码。我不明白的意思是有人在评论nextkingX:-ageX时说的话。现在,该评论已被该人删除。我不知道这个解决方案怎么能给出正确的答案。这个解决方案取决于我如何陈述事实的顺序。不管怎样,我从stack Overflow中的另一个成员那里得到了答案。你是说我将规则更改为nextkingX:-ageX,\ux?对于那个种情况,若我改变事实的顺序,我将不会得到正确的结果。我需要查询以年龄降序显示姓名。我不太懂代码。无论如何,我得到的答案也不正确。我以爱德华、查尔斯、安、安德鲁的身份得到了答案。正确的答案应该是查尔斯、安、安德鲁、爱德华,因为这是年龄递减的正确顺序。我不太理解代码。这段代码是你写的还是来自其他地方?简单地说,一个人成为下一任国王的条件是什么?该法典暗示下一任国王是55岁或至少比其他人年长的任何人。基于现有的数据,可能是任何人。我自己编写的代码。我不明白的意思是有人在评论nextkingX:-ageX时说的话。现在,该评论已被该人删除。我不知道这个解决方案怎么能给出正确的答案。这个解决方案取决于我如何陈述事实的顺序。不管怎样,我从stack Overflow的另一位成员那里得到了答案谢谢你,威廉。这是一个完美的答案,尽管我不明白它是如何工作的。需要进一步了解它。就像你说的,改变事实不会影响我的结果。谢谢你,谢谢你,威廉。这是一个完美的答案,尽管我不明白它是如何工作的。需要进一步了解它。就像你说的,改变事实不会影响我的结果。非常感谢。