在Prolog编程中,计算Y实际发生的次数(X,Y)
我是prolog编程新手,我正在尝试使用它 我有两个问题在Prolog编程中,计算Y实际发生的次数(X,Y),prolog,Prolog,我是prolog编程新手,我正在尝试使用它 我有两个问题 假设我有一些事实 事实('A','B')。 事实('A','C')。 事实('A','D') 当我写事实('A',X'时,X将是3个值'B','C','D' 我如何编写一个规则来获得“a”有一对的次数,在这种情况下,答案是3 假设我有一个事实 a([1,2,4,5]) 我如何编写一个规则来循环元素以添加它们,即找到sigma 谢谢您可以收集解决方案列表并获取列表大小: ?- findall(X, fact('A',X), List),
谢谢您可以收集解决方案列表并获取列表大小:
?- findall(X, fact('A',X), List), length(List,Count).
List = ['B', 'C', 'D'],
Count = 3.
或者更好地使用以下聚合谓词:
注意插入符号
X^
表示X
不是一个变量,在该变量上聚合(count,Goal_,with_X,count)。
应该回溯(给出三次1的计数)但是目标的一个自由变量带有_X
,该变量随溶液袋的大小而变化,应评估溶液袋的大小。您可以收集溶液列表并获得列表的大小:
?- findall(X, fact('A',X), List), length(List,Count).
List = ['B', 'C', 'D'],
Count = 3.
或者更好地使用以下聚合谓词:
注意插入符号
X^
表示X
不是一个变量,在该变量上聚合(count,Goal_,with_X,count)。
应该回溯(给出三次1的计数)但是,目标的一个自由变量带有_X
,该变量随溶液袋的大小而变化,应评估溶液袋的大小。如果您只需要计算溶液,并且您正在使用SWI Prolog,请使用聚合\u all
:
?- aggregate_all(count, fact('A', _), N).
这样,您就不需要对变量进行存在性限定,只需在查询中使用匿名变量来“跳过”它即可
这还可以正确计算0个解决方案,而无需进一步的代码技巧:
?- aggregate_all(count, fail, N).
要对列表求和,可以使用库(列表)中的sum\u list/2
。请注意,如果您有一个可回溯谓词(事实表)而不是列表,那么也可以使用库(聚合)来实现这一点。这也是表示数据库中事物的“列表”的更常见的方法
a(1).
a(2).
a(4).
a(5).
这是您通常如何查找表中所有行的总和:
?- aggregate_all(sum(X), a(X), Sum).
Sum = 12.
当然,表中可以有更多的列
p(a, 3).
p(b, 2).
p(b, 1).
p(a, 2).
p(a, 0).
你可以这样求和:
?- aggregate_all(sum(X), p(a, X), Sum).
Sum = 5.
?- aggregate_all(sum(X), p(b, X), Sum).
Sum = 3.
?- aggregate_all(sum(X), p(foo, X), Sum).
Sum = 0.
?- aggregate_all(sum(X), p(_, X), Sum). % total sum
Sum = 8.
相反,您可以使用aggreagate
获取不同的组:
?- aggregate(sum(X), p(A, X), Sum).
A = a,
Sum = 5 ;
A = b,
Sum = 3.
如果您只需要计算解决方案并使用SWI Prolog,请使用
aggregate\u all
:
?- aggregate_all(count, fact('A', _), N).
这样,您就不需要对变量进行存在性限定,只需在查询中使用匿名变量来“跳过”它即可
这还可以正确计算0个解决方案,而无需进一步的代码技巧:
?- aggregate_all(count, fail, N).
要对列表求和,可以使用库(列表)中的sum\u list/2
。请注意,如果您有一个可回溯谓词(事实表)而不是列表,那么也可以使用库(聚合)来实现这一点。这也是表示数据库中事物的“列表”的更常见的方法
a(1).
a(2).
a(4).
a(5).
这是您通常如何查找表中所有行的总和:
?- aggregate_all(sum(X), a(X), Sum).
Sum = 12.
当然,表中可以有更多的列
p(a, 3).
p(b, 2).
p(b, 1).
p(a, 2).
p(a, 0).
你可以这样求和:
?- aggregate_all(sum(X), p(a, X), Sum).
Sum = 5.
?- aggregate_all(sum(X), p(b, X), Sum).
Sum = 3.
?- aggregate_all(sum(X), p(foo, X), Sum).
Sum = 0.
?- aggregate_all(sum(X), p(_, X), Sum). % total sum
Sum = 8.
相反,您可以使用aggreagate
获取不同的组:
?- aggregate(sum(X), p(A, X), Sum).
A = a,
Sum = 5 ;
A = b,
Sum = 3.
@NickyPratama要在列表上求和,实际上有一个谓词,所以你可以这样做:
a(L),sum\u list(L,sum)。
@NickyPratama注意,aggregate/3有一个边缘情况:如果没有解决方案,则如果失败,而不是给出Count==0
。使用(聚合(count,X^事实(c,X),count)->true;count=0)。
确保您得到的计数为0,而不是失败。您可以使用聚合\u all
来代替,它更明显,并且不会在您的注释中出现边缘情况。Try:?-aggregate\u all(count,介于(1,3,u),N)之间)。
(不需要“存在限定变量”)和?-aggregate\u all(count,fail,N)。
与bagof/setof和findall在语义和实现上的差异有点相关。另请参阅文档。@NickyPratama您在事实中有您的数字列表:a([1,2,4,5])。
。因此,首先,您必须从事实中获取该列表并将其放入变量中,这样做:a(L)。
。现在L
是[1,2,4,5]
。现在您可以执行'sum_list(L,sum)。。但是当然,在执行单个目标的上下文中,
L`只是相同的L
(否则它就完全不同了L
s),所以您将两条指令一起运行到一个目标中:a(L),sum\u list(L,sum)。
@NickyPratama完整的故事是,您几乎永远不会保存这样的事实:a([1,2,4,5])
,这通常被写成一个表。看到我的答案了。@NickyPratama要在列表上求和,实际上有一个谓词,所以你可以这样做:a(L),sum\u list(L,sum)。
@NickyPratama注意,aggregate/3
有一个边缘情况:如果没有解决方案,则不给出Count==0
。使用(聚合(count,X^事实(c,X),count)->true;count=0)。
确保您得到的计数为0,而不是失败。您可以使用聚合\u all
来代替,它更明显,并且不会在您的注释中出现边缘情况。Try:?-aggregate\u all(count,介于(1,3,u),N)之间)。
(不需要“存在限定变量”)和?-aggregate\u all(count,fail,N)。
与bagof/setof和findall在语义和实现上的差异有点相关。另请参阅文档。@NickyPratama您在事实中有您的数字列表:a([1,2,4,5])。
。因此,首先,您必须从事实中获取该列表并将其放入变量中,这样做:a(L)。
。现在L
是[1,2,4,5]
。现在您可以执行'sum_list(L,sum)。。但是当然,在一个要执行的单一目标的上下文中,
L`只是相同的L