Здесь вы пытаетесь понять точное свойство завершения вашей программы, что немного удивительно, когда вы исходите из процедурных языков. В Прологе есть несколько чередующихся потоков управления, что часто затрудняет фактическое выполнение.
Чтобы понять это, вы можете проследить программу шаг за шагом, чтобы получить представление о том, что на самом деле происходит, но этот метод довольно быстро становится сложным. И ваша программа настолько проста, насколько это возможно. Вместо этого я покажу вам другой метод, использующий failure-slice.
Вам очень повезло, что вы использовали запрос even(3)
, который сразу показывает наличие проблемы. Вы могли бы использовать другой запрос, например even(2).
, который не показывает проблему сразу. На самом деле Пролог отлично справляется с этим запросом. Все выглядит хорошо, если вы не попросите увидеть дополнительные ответы.
Итак, как мы можем убедиться, что столкнемся с проблемой как можно скорее? Один из способов сделать это — задать вместо этого запрос even(2), false
. В этом случае мы ожидаем, что запрос завершится ошибкой, поскольку false
никогда не завершается успешно. Однако вместо сбоя запрос может привести к бесконечному циклу (или ошибке). Добавляя false
в конце, мы говорим: пропустить все ответы и просто показать, завершается ли запрос.
Что хорошо в (чистом, монотонном) Прологе, так это то, что мы можем сделать то же самое с вашей программой. Поэтому мы можем добавить цели false
в вашу программу. Если результирующая программа, называемая срезом отказа, теперь зацикливается, то и исходная программа будет фактически зацикливаться.
Вот минимальный фрагмент отказа, который все еще зацикливается:
even(0) :- false.
even(X) :- odd(Y), false, X is Y+1, X>0.
odd(1) :- false.
odd(X) :- even(Y), false, X is Y+1, X>1.
Именно эта крошечная оставшаяся часть отвечает за все циклы. Теперь вы можете не только обосновать, почему even(2)
зацикливается, но и увидеть кое-что еще более общее: этот фрагмент отказа будет зацикливаться независимо от аргумента для even/1
. Таким образом, он будет зацикливаться для любого запроса!
Дополнительную информацию см. в разделе failure-slice.
person
false
schedule
11.09.2013