Посчитать количество вызовов пункта

У меня есть пункт вроде следующего:

lock_open: -
        conditional_combination (Х),
        равным (X,[8,6,5,3,6,9]),!,
        печать (X).

этот пункт успешен. Но я хочу знать, сколько раз вызывается conditional_combination() equal(X,[8,6,5,3,6,9]) стало правдой. программа должна генерировать перестановку, следуя некоторым правилам. И мне нужно, сколько перестановок нужно сгенерировать, чтобы получить конкретное значение, например 865369.

2 ответа

Решение

То, что вы на самом деле хотите, - это что-то немного другое: вы хотите посчитать количество ответов (пока) цели.

Следующий предикат call_nth(Goal_0, Nth) преуспевает как call(Goal_0) но имеет дополнительный аргумент, который указывает, что найденный ответ является n-ным ответом. Это определение очень специфично для SWI или YAP. Не используйте такие вещи, как nb_setarg/3 в ваших общих программах, но используйте их для хорошо инкапсулированных случаев, как этот. Даже в этих двух системах точное значение этих конструкций недостаточно определено для общего случая. Вот определение для SICStus.

call_nth (цель_0, C):-
   State = count(0,_), % обратите внимание на дополнительный аргумент, который остается переменной
   Goal_0,
   arg(1, State, C1),
   С2 представляет собой С1+1,
   nb_setarg(1, штат, C2),
   С = С2.

Более надежная абстракция обеспечивается 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).
I = Nth, Nth = 1;
I = Nth, Nth = 2;
I = Nth, Nth = 3;
I = Nth, Nth = 4;
I = Nth, Nth = 5.

Так что просто оберните это вокруг:

lock_open: -
   call_nth (условная_комбинация (X), Nth),
   Х = [8,6,5,3,6,9],!,
   ....

Если вы используете пролог SWI, вы можете использовать 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).

Другие прологи имеют другие способы сделать то же самое, ищите глобальные переменные в вашей реализации пролога. В этом фрагменте я использовал термин ctr держать текущий счетчик цели. Вы можете использовать любой термин, который не используется в вашей программе.

Работая над модулем "микро", я недавно изобрел опорные точки. Они вдохновлены шаблоном потока / канала для передачи данных. Pivot - это ограниченная очередь максимальной длины, 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.
Другие вопросы по тегам