Prolog 如何计算谓词

Prolog 如何计算谓词,prolog,Prolog,我正在寻找一种计算谓词数量的方法。 例如: %事实 has_subclass(thing,animal). has_subclass(thing,tree). has_subclass(thing,object). %我问 count_has_subclass(thing,X). %结果 X=3。对于像您的示例这样的事实: count_has_subclass(What, Count):- findall(1, call(has_subclass(What, _)), L), len

我正在寻找一种计算谓词数量的方法。 例如:

%事实

has_subclass(thing,animal).
has_subclass(thing,tree).
has_subclass(thing,object).
%我问

count_has_subclass(thing,X).
%结果


X=3。

对于像您的示例这样的事实:

count_has_subclass(What, Count):-
  findall(1, call(has_subclass(What, _)), L),
  length(L, Count).

对于像你的例子这样的事实:

count_has_subclass(What, Count):-
  findall(1, call(has_subclass(What, _)), L),
  length(L, Count).
我们可以使用,然后使用获得列表的长度:

count_has_subclass(What, N):-
    findall(X, has_subclass(What, X), L),
    length(L, N).
但是,如果
has_subclass/2
可能多次为给定的键(如
thing
)生成相同的值,那么我们可以将其用作重复过滤器,例如:

count_has_subclass(What, N):-
    findall(X, has_subclass(What, X), L),
    sort(L, S),  %% remove duplicates
    length(S, N).
count\u有子类(What,N):-
findall(X,has_子类(What,X),L),
排序(L,S),%%删除重复项
长度(S,N)。
请注意,如果
What
是一个自由变量,那么您将计算
has_subclass(u,u)的所有YELD。
(可选在第二个参数上使用uniqness筛选器)。

我们可以使用它,然后使用来获得列表的长度:

count_has_subclass(What, N):-
    findall(X, has_subclass(What, X), L),
    length(L, N).
但是,如果
has_subclass/2
可能多次为给定的键(如
thing
)生成相同的值,那么我们可以将其用作重复过滤器,例如:

count_has_subclass(What, N):-
    findall(X, has_subclass(What, X), L),
    sort(L, S),  %% remove duplicates
    length(S, N).
count\u有子类(What,N):-
findall(X,has_子类(What,X),L),
排序(L,S),%%删除重复项
长度(S,N)。

请注意,如果
What
是一个自由变量,那么您将计算
has_subclass(u,u)的所有yeld。
(可选地在第二个参数上使用uniqness过滤器)。例如,假设以下数据库:

has_subclass(thing,animal).
has_subclass(thing,tree).
has_subclass(thing,object).

has_subclass(animal,cat).
has_subclass(animal,dog).

has_subclass(tree,pine).
has_subclass(tree,oak).
定义如下:

subclass_count(Class, Count) :-
    setof(Subclass, has_subclass(Class, Subclass), Subclasses),
    length(Subclasses, Count).
电话示例:

| ?- subclass_count(Class, Count).

Class = animal
Count = 2 ? ;

Class = thing
Count = 3 ? ;

Class = tree
Count = 2

yes
如果您尝试其他答案中的
findall/3
解决方案,我们会得到:

| ?- count_has_subclass(What, Count).

Count = 7

但请注意,此解决方案也有一个合理的解释,即在未指定类时返回所有现有子类的数量。

使用标准的
集合/3
是一个更好的选择,因为它允许轻松定义更通用的谓词,可以在类参数未绑定时枚举解决方案。例如,假设以下数据库:

has_subclass(thing,animal).
has_subclass(thing,tree).
has_subclass(thing,object).

has_subclass(animal,cat).
has_subclass(animal,dog).

has_subclass(tree,pine).
has_subclass(tree,oak).
定义如下:

subclass_count(Class, Count) :-
    setof(Subclass, has_subclass(Class, Subclass), Subclasses),
    length(Subclasses, Count).
电话示例:

| ?- subclass_count(Class, Count).

Class = animal
Count = 2 ? ;

Class = thing
Count = 3 ? ;

Class = tree
Count = 2

yes
如果您尝试其他答案中的
findall/3
解决方案,我们会得到:

| ?- count_has_subclass(What, Count).

Count = 7

但请注意,此解决方案也有一个合理的解释,即在未指定类时返回所有现有子类的数量。

仅为计算解决方案而构建列表似乎是“旧式”,但在传统的Prolog中,只有DB(assert/retract)替代方案可以克服计算的“无状态”性质。事实上,findall/3和friends的内置代码可以(天真地)通过assert/retract重写。但自80年代初以来,出现了一些情况:)。我用SWI-Prolog进行了说明,但是——或多或少天真地——所有这些都可以通过assert/retract实现。当然,大多数Prolog实现都有“非逻辑”(或“命令式”或“不纯”)功能来实现这样的基本任务,而无需求助于重量级的DB接口,如/3、/2等

我离题了。。。库()应首先显示:

?- aggregate(count, T^has_subclass(thing,T), C).
C = 3.
这个库非常值得研究,它比高效的计数做得更多。。。 另一个最近添加的是library()。我猜它并不比setof/3+length/2更有效,但它本身就很有趣。计数更为复杂,使用/2:

有些更简单,基于/3(以及@false的帮助):


仅仅为了计算解决方案而构建一个列表似乎是“旧式的”,但在传统的Prolog中,只有DB(断言/收回)替代方案可以克服计算的“无状态”性质。事实上,findall/3和friends的内置代码可以(天真地)通过assert/retract重写。但自80年代初以来,出现了一些情况:)。我用SWI-Prolog进行了说明,但是——或多或少天真地——所有这些都可以通过assert/retract实现。当然,大多数Prolog实现都有“非逻辑”(或“命令式”或“不纯”)功能来实现这样的基本任务,而无需求助于重量级的DB接口,如/3、/2等

我离题了。。。库()应首先显示:

?- aggregate(count, T^has_subclass(thing,T), C).
C = 3.
这个库非常值得研究,它比高效的计数做得更多。。。 另一个最近添加的是library()。我猜它并不比setof/3+length/2更有效,但它本身就很有趣。计数更为复杂,使用/2:

有些更简单,基于/3(以及@false的帮助):


你试了什么?什么不起作用?你试了什么?什么不起作用?这是公认的答案,但使用
setof
似乎要干净得多,@User9213:
setof(…)
有一个小问题:如果它找不到一个可以满足的项,那么它将失败,因此它无法返回
0
。例如,
count\u has\u subclass(blahblah,N)
不会返回
0
,而是
false
。这是公认的答案,但使用
setof
似乎要干净得多。@User9213:
setof(…)
有一个小问题:如果它找不到一个可以满足的项,那么它就会失败,因此它不能返回
0
。例如,
count\u has\u子类(blahblah,N)
将不会返回
0
,而是
false