Recursion 计算子句的调用数
我有一个条款如下: lock_open:- conditional_combination(X), equal(X,[8,6,5,3,6,9]),!, print(X). 锁定打开:- 条件_组合(X), 等于(X,[8,6,5,3,6,9]),!, 打印(X)。Recursion 计算子句的调用数,recursion,count,prolog,clause,Recursion,Count,Prolog,Clause,我有一个条款如下: lock_open:- conditional_combination(X), equal(X,[8,6,5,3,6,9]),!, print(X). 锁定打开:- 条件_组合(X), 等于(X,[8,6,5,3,6,9]),!, 打印(X)。 本条款生效。但是我想知道在equal(X,[8,6,5,3,6,9])变为真之前,条件_composition()被调用了多少次。该程序通过遵循一些规则来生成置换。我需要知道需要生成多少
本条款生效。但是我想知道在
equal(X,[8,6,5,3,6,9])
变为真之前,条件_composition()被调用了多少次。该程序通过遵循一些规则来生成置换。我需要知道需要生成多少个置换才能得到865369这样的特定值。如果您使用SWI prolog,您可以使用nb_getval/2
和nb_setval/2
来实现您想要的:
lock_open:-
nb_setval(ctr, 0), % Initialize counter
conditional_combination(X),
nb_inc(ctr), % Increment Counter
equal(X,[8,6,5,3,6,9]),
% Here you can access counter value with nb_getval(ctr, Value)
!,
print(X).
nb_inc(Key):-
nb_getval(Key, Old),
succ(Old, New),
nb_setval(Key, New).
其他prolog也有其他方法来做同样的事情,在prolog实现中寻找全局变量。在这段代码中,我使用术语
ctr
来保存当前目标计数器。您可以使用程序中未使用的任何术语。您真正想要的是稍微不同的东西:您想要计算一个目标的答案数(到目前为止)
下面的谓词call\n(Goal\u 0,nth)
与call(Goal\u 0)
一样成功,但有一个附加参数指示找到的答案是第n个答案。该定义对SWI或YAP具有高度特异性。不要在您的常规程序中使用类似于nb_setarg/3
的东西,但要将它们用于封装良好的情况,如本例。甚至在
在这两个系统中,这些结构的确切含义在一般情况下没有得到很好的定义
?呼叫n(介于(1,5,I)和n之间)。
I=n,n=1;
I=n,n=2;
I=n,n=3;
I=n,n=4;
I=n,n=5。
因此,简单地把它包装起来:
lock_open :-
call_nth(conditional_combination(X), Nth),
X = [8,6,5,3,6,9],
!,
....
锁定打开:-
调用n次(条件组合(X),n次),
X=[8,6,5,3,6,9],
!,
....
在制作“micro”模块时,我最近发明了枢轴。它们的灵感来自于传递数据的螺纹/管道模式。pivot是一个最大长度为1的有界队列,pivot_put/1也会复制给定项。但出于性能方面的原因,它们不使用同步和非阻塞
就目前而言,它们与nb_setarg/3非常相似,只是它们不破坏Prolog术语,而是更新Java数据结构。因此,它们比非逻辑项操作稍微安全一点。而且它们不需要一些调用_cleanup/3,因为它们是Java垃圾收集的
就目前而言,它们比nb_setarg/3更相似,而不是使用一些显式的分配和解除分配结构。例如,SICStus Prolog的解决方案可以是:
call_nth(Goal_0, Nth) :-
new(unsigned_32, Counter),
call_cleanup(call_nth1(Goal_0, Counter, Nth),
dispose(Counter)).
call_nth1(Goal_0, Counter, Nth) :-
call(Goal_0),
get_contents(Counter, contents, Count0),
Count1 is Count0+1,
put_contents(Counter, contents, Count1),
Nth = Count1.
使用pivots,甚至没有32位限制,我们可以直接执行以下操作:
call_nth(G, C) :-
pivot_new(P),
pivot_put(P, 0),
call(G),
pivot_take(P, M),
N is M+1,
pivot_put(P, N),
C = N.
在
条件组合/1
中调用nb_setval/2
会影响结果。像ctr
这样的名称可能用于其他计数…@false:true,OP应该使用程序中未使用的任何术语。问题是,如果不检查整个程序,您无法保证这一点。您是对的,但如果您采取这种立场,那么您将永远不会使用assert/call/retract或任何具有全局效果的术语。事实上,就像在任何语言中一样,如果你使用任何全球语言,你都必须谨慎……我不同意:更新知识库需要像assert/retract这样的东西。还有一些方法可以防止一个全球卫星的多种用途成为可能。以使用asserta/retract的findall/3为例。您不能嵌套这样的调用,也不能同时有两个调用。我看到了一种使用这样的原语在时间和空间上实现聚合器O(N)的方法。谢谢必须重新考虑limit/2和offset/2的实现,可能更原始、更通用的谓词是call\n/2。我没有意识到可以这样调用目标(清单call\n/2
的第三行)。我以为一个人总是需要呼叫(目标),但显然,只要目标就足够了!
lock_open :-
call_nth(conditional_combination(X), Nth),
X = [8,6,5,3,6,9],
!,
....
call_nth(Goal_0, Nth) :-
new(unsigned_32, Counter),
call_cleanup(call_nth1(Goal_0, Counter, Nth),
dispose(Counter)).
call_nth1(Goal_0, Counter, Nth) :-
call(Goal_0),
get_contents(Counter, contents, Count0),
Count1 is Count0+1,
put_contents(Counter, contents, Count1),
Nth = Count1.
call_nth(G, C) :-
pivot_new(P),
pivot_put(P, 0),
call(G),
pivot_take(P, M),
N is M+1,
pivot_put(P, N),
C = N.