2013-04-10 2 views
-1

Я учусь Пролог для университетского экзамена с помощью SWI Prolog и у меня есть некоторые сомнения по поводу различий между двумя различными решения следующей задачи:Некоторые вопросы об использовании CUT в этой Prolog упражнения

Определи пункт граф (X, L, NumX), где Х представляет собой атом, L представляет собой перечень и NumX это число вхождений, что Х появляется в L.

Это первое решение:

count0(_,[],0). 

count0(A, [A|Tail], N) :- 
      count0(A,Tail,N1), % L'elemento cercato appare N1 volte nella sottolista 
       N is N1+1.  % N vale N1+1 

count0(A, [B|Tail], N) :- 
      A\=B,   % A è diverso da B 
     count0(A,Tail,N). % N è il numero di occorrenze di A nella sottolista 

Это второе решение:

count1(_,[],0). 

count1(A, [A|Tail], N) :- !, 
         count1(A, Tail, N1), 
       N is N1+1. 

count1(A, [_|Tail], N) :- count1(A, Tail, N). 

Моя проблема заключается в том, что я не понимая, какую роль она играет в CUT во второй версии

Я знаю, что CUT предотвращает откат в определенную точку, где выполняется CUT.

Первая версия программы проверяет, отлична ли A от B во втором правиле (мне нужно это? Если первое правило не выполнено, это означает, что A не объединяется с HEAD списка, поэтому Глава списка он отличается от элемента а)

Вторая версия не выполняет эту проверку во втором правиле, но поставить сокращение в первом правиле ...

это может быть, зависит от тот факт, что (во второй версии), если я не предотвращаю обратное отслеживание, происходит следующее: после этого Prolog дает мне первый (правильный) ответ, если я принудительно использую backtracking; бывает, что используют второе правило:

count1(A, [_|Tail], N) :- count1(A, Tail, N). 

принимая другую ветвь в вычислениях и в этой отрасли я не имею N не является N + 1?

ответ

1

Первая версия оставляет точку выбора во втором предложении, тогда как вторая версия совершает (с разрезом) это предложение, когда оно входит во второе предложение.

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

Вы можете увидеть это сами, если вы проследите обе процедуры с простым списком ввода, например, из 1 элемента.

?- count0(a,[a], Count). 

Первая версия вашей программы будет соответствовать элементу с заголовком списка и выполнить рекурсию. Однако он оставит там выбор, чтобы увидеть другие альтернативы, если потребуется. Затем рекурсия заканчивается из-за базового футляра (пустой список), и вы получаете свой результат Count = 1.

Если вы теперь запросите пролог для других альтернатив, у него все еще есть этот пункт выбора, чтобы он попытался сделать предложение thirc. Если вы явно не проверяете, что A и B разные, он будет рекурсивно называть себя (опять же с пустым списком) и возвращать Count = 0, что является неправильным ответом!

Теперь вторая версия вашей программы (та, которая использует разрез). Когда пролог входит во второе предложение с пунктом a, он фиксируется с разрезом, поэтому он не оставит точку выбора. Теперь вы выполните рекурсию и закончите с правильным результатом Count = 1.

Если вы спросите пролог о других альтернативах, он скажет, что проверить нечего. В результате вырезания нет необходимости проверять, что A и B больше отличаются, потому что вы уверены, что они будут разными, поскольку в противном случае второе условие было бы выполнено, а третье предложение не было проверено.

+0

Хорошо, теперь для меня это более понятно ... последний вопрос: во второй версии программы (которая использует разрез) порядок правила важен, правильно? – AndreaNobili

+1

@AndreaNobili: Да, это важно. Если вы поменяете два последних предложения, вы получите неверные результаты (а также правые). – gusbro

Смежные вопросы