Почему эта команда вызывает переполнение стека в прологе?
-
27-10-2019 - |
Вопрос
У меня есть следующий фрагмент кода Prolog:
num(0).
num(X) :- num(X1), X is X1 + 1.
fact(0,1) :-!.
fact(X,Y) :- X1 is X-1, fact(X1,Y1), !, Y is Y1 * X.
fact(X) :- num(Y), fact(Y,X).
Может кто -нибудь объяснить, почему следующая команда вызывает переполнение стека? Заранее спасибо.
fact(6).
Решение
Во -первых, глядя на правила
num(0).
num(X) :- num(X1), X is X1 + 1.
предикат num(Y)
будет непосредственно действительным для Y = 0
.
Таким образом, правило
fact(X) :- num(Y), fact(Y,X).
может быть упрощен как
fact(X) :- fact(0,X).
это найдет матч для fact(0,1)
. Анкет За X = 6
, вместо этого происходит, поскольку ни одно правило не определяет предикат для fact(0,6)
, поиск начинается с fact(-1,V1)
, следовал с fact(-2,V2)
и т. д. до тех пор, пока не произойдет матч для fact(-value, Var)
где локальный результат будет найден.
Этого не может произойти, и бесконечная петля потребляет весь стек, пока ошибка не будет вызвана.
Другие советы
Причина почему fact(6)
не заканчивается, можно найти в следующем неудача:
?- fact(6).num (0):- ЛОЖЬ. num(X) :- num(X1), ЛОЖЬ,X is x1 + 1. fact(X) :- num(Y), ЛОЖЬ,факт (y, x).
Потому что Этот фрагмент не заканчивается, а также ваша первоначальная программа не прекращается. Обратите внимание, что неверно не зависит от определения fact/2
! В лучшем случае ваша программа может преуспеть, но она никогда не потерпит неудачу.
Подумайте об использовании Другое определение fact/2
, что заканчивается также для fact(N, 6).