Prolog-如何检查谓词是否多次成功

Prolog-如何检查谓词是否多次成功,prolog,Prolog,我有这样一个事实数据库: li(a,2). li(b,3). li(b,1). li(c,2). li(d,1). li(d,1). 我需要编写一个谓词more(+Let),如果它存在多个事实li(Let,u),则会成功 例如,查询more(b)和more(d)会成功,但more(a)和more(c)不会成功。 我的想法是检查李是否不止一次成功,但我不知道怎么做 试试看: 将d抽象出来并生成谓词是很简单的。对吧?:) 如果您不想使用任何谓词,如findall,您可以更改知识的表示形式-可以说

我有这样一个事实数据库:

li(a,2).
li(b,3).
li(b,1).
li(c,2).
li(d,1).
li(d,1).
我需要编写一个谓词more(+Let),如果它存在多个事实li(Let,u),则会成功

例如,查询more(b)和more(d)会成功,但more(a)和more(c)不会成功。 我的想法是检查李是否不止一次成功,但我不知道怎么做

试试看:

d
抽象出来并生成谓词是很简单的。对吧?:)


如果您不想使用任何谓词,如
findall
,您可以更改知识的表示形式-可以说,将其降低一个级别:

my_knowledge(li, [a-2,b-3,b-1,c-2,d-1,d-1]).
然后您可以使用SWI Prolog的谓词来处理它:

select_knowledge(kn, key, R):-
  my_knowledge(kn,L),
  select_key(L,key,R).

select_key(L,K,R):-
  select(K-X,L,L1) -> R=[X|R1], select_key(L1,K,R1)
  ; R = [].
您可以将最后一个谓词重写为列表上的基本递归,然后在获得前N个结果后将其调整为停止。

SWI Prolog has library()

测试:

学习起来并不容易,但处理这些普通任务很有用。如果您有一个非常大的代码库,那么findall(以及在内部使用findall的聚合)可能效率低下,构建一个列表只是为了计算它的元素

然后你们可以使用一个基于副作用的谓词:在相关的答案中你们会发现这样的效用。要获得最大效率,请参阅注释,其中说明了如何使用nb_setval/nb_getval

more_than_once(Goal) :-
   \+ \+ call_nth(Goal,2).
使用中定义的
调用第/2个

与提出的其他解决方案相比,该解决方案的最大优势在于,即使有非常大的答案序列,它也会迅速成功。事实上,它甚至会成功地找到无限多的答案:

?- more_than_once(repeat). true. ?- more_than_once(between(1,100000,_)). true. ?不止一次(重复)。 对。 ?超过一次(在(1100000,)之间)。 对。
(调用第/2次调用的实现使用了一些非标准的、低级的SWI内置。这是可以避免的,但更令人头痛。)

hmm,调用
findall(X,pred(X),[[uu,| |]
可以理解为显示了将调用
pred
的实际调用次数减少到不超过两次的意图。。。但这只能在执行层面上实现,对吗?或者它可能需要为谓词加上另一个名称,比如
findsome
:)
findall
毕竟说的是“全部查找”。您的解决方案看起来不错,但我正在搜索一个只使用谓词本身或基本谓词(如成员、追加、长度和明显的比较)的解决方案。@markusian那么您就不走运了。计算一个谓词成功的次数不是逻辑,而是逻辑之上的——也就是说,它不是关于证明某事,而是关于证明某事的机制的运作。至少您必须使用
断言
/
收回
,或
标记
等。
findall
更易于使用。感谢您的解释!因此,如果计算谓词成功的次数不是逻辑,我应该考虑另一种方法。@markusian,这就是使用
标志
,或
断言
/
收回
,或
findall
,或
nb_setarg
的方法。编程语言的所有合法部分,Prolog。has sample
成功\u n\u次
谓词。我刚刚发现我的问题比我想象的要简单,因为谓词more应该回答至少两个事实li(Let,X),li(Let,Y),X不等于Y。我简单地用
more(L):-li(L,X),li(L,Y),X\=Y来解决它
?- more(b).
true.

?- more(a).
false.
more_than_once(Goal) :-
   \+ \+ call_nth(Goal,2).
?- more_than_once(repeat). true. ?- more_than_once(between(1,100000,_)). true.