13

我有一个如下的子句:

lock_open:-
        条件组合(X),
        等于(X,[8,6,5,3,6,9]),!,
        打印(X)。

此子句成功。equal(X,[8,6,5,3,6,9])但我想知道 conditional_combination() 在变为 true之前被调用了多少次。该程序是通过遵循一些规则来生成一个排列。我需要生成多少排列才能获得像 865369 这样的特定值。

4

3 回答 3

12

您真正想要的是稍微不同的东西:您想要计算目标的答案数量(到目前为止)。

以下谓词call_nth(Goal_0, Nth)成功,call(Goal_0)但有一个附加参数,表明找到的答案是第 n 个答案。此定义高度特定于 SWI 或 YAP。不要在的一般程序中使用类似的东西nb_setarg/3,而是将它们用于封装良好的情况,就像这个一样。即使在这两个系统中,这些构造的确切含义也没有针对一般情况很好地定义。这是 SICStus 的定义

call_nth(Goal_0, C) :-
   State = count(0,_), % 注意额外的参数,它仍然是一个变量
   目标_0,
   arg(1,状态,C1),
   C2 是 C1+1,
   nb_setarg(1,状态,C2),
   C = C2。

Eclipse 提供了一个更健壮的抽象:

call_nth(Goal_0, Nth) :-
   shelf_create(counter(0), CounterRef),
   call(Goal_0),
   shelf_inc(CounterRef, 1),
   shelf_get(CounterRef, 1, Nth).
?- call_nth((1,5,I),Nth)。
我 = 第 N, 第 N = 1 ;
我 = 第 N,第 N = 2;
我 = 第 N,第 N = 3;
我=第N次,第N次= 4;
我 = 第 N 个,第 N 个 = 5。

所以简单地把它包起来:

lock_open :-
   call_nth(conditional_combination(X), Nth),
   X = [8,6,5,3,6,9],
   !,
   ……
于 2012-07-09T17:41:47.227 回答
4

如果您使用的是 SWI prolog,您可以使用nb_getval/2nb_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).

其他 prologs 有其他方法可以做同样的事情,在你的 prolog 实现中寻找全局变量。在此代码段中,我使用该术语ctr来保存当前目标计数器。您可以使用程序中未使用的任何术语。

于 2012-07-06T17:30:11.943 回答
1

在开发“微型”模块时,我最近发明了枢轴。它们受到线程/管道模式的启发来传递数据。枢轴是最大长度为 1 的有界队列,pivot_put/1 也是给定术语的副本。但是出于性能原因,它们不使用同步并且是非阻塞的。

到目前为止,它们与 nb_setarg/3 非常相似,只是它们不破坏 Prolog 术语,而是更新 Java 数据结构。因此,它们比非逻辑项操作更安全一些。他们也不需要一些 call_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.

使用数据透视表,甚至没有 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.
于 2019-03-05T16:43:38.803 回答