Результаты повторения хранятся в списке в прологе
Я пытаюсь создать Пролог-программу для решения рекуррентного уравнения:
F (1)=2, f (2)=5, f (n)=f (n-1)+2*f (n-2)
Я справился с функцией rec ниже, но у меня возникают проблемы, когда я хочу сохранить результат в списке (по функции recList).
Это моя реализация:
rec(1,2).
rec(2,5).
rec(X,N) :- X1 is X-1, X2 is X-2, rec(X1,N1), rec(X2,N2), N is N1+2*N2.
recList(0,[]).
recList(X,[N|L]) :- rec(X,N), X1 is X-1, recList(X1,L).
Моя реализация recList работает для вызова его по первому значению
?- recList(4,X).
->
X = [19, 9, 5, 2] .
Но это не так, когда я называю его вторым, если он длиннее двух элементов:
?- rekurList(X,[2]).
X = 1 .
?- rekurList(X,[5,2]).
X = 2 .
?- rekurList(X,[9,5,2]).
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR: [9] rec(_12587334,9)
ERROR: [8] rekurList(_12587360,[9,5|...]) at /locaiton/rec.pl:6
ERROR: [7] <user>
Что случилось, пожалуйста?
1 ответ:
Предикат
is/2
терпит неудачу, посколькуis/2
оценивает правую структуру как арифметическое выражение. Если это не является допустимым арифметическим выражением или числом,is/2
терпит неудачу. Поэтому, когда вы звонитеrecList(X, [19, 9, 5, 2]).
Вы получаете
rec/2: Arguments are not sufficiently instantiated
. Если вы запустите Трейсер (в SWISH, который является SWI на линии:trace, recList(X, [19, 9, 5, 2]).
в ECLiPSe вы можете использоватьtkeclipse Tools->Tracer
), вы получите что-то вроде:Call:recList(_13806, [19, 9, 5, 2]) Call:rec(_13806, 19) Call:_14048 is _13806+-1 Exception:_14102 is _13806+-1 is/2: Arguments are not sufficiently instantiated
Для решения этой задачи вы можете использовать библиотеку
clpfd
таким образом (я написал решение с помощью SWI)::- use_module(library(clpfd)). rec(1,2). rec(2,5). rec(X,N):- X1 #> 0, X1 #= X-1, rec(X1,N1), X2 #> 0, X2 #= X-2, rec(X2,N2), N #= N1+2*N2, !. %notice the cut (!) recList(0,[]):-!. recList(X,[N|L]):- rec(X,N), X1 #= X-1, recList(X1,L).
Запрос:
Обратите внимание, что вырезать?- recList(X, [19, 9, 5, 2]). X = 4. false. ?- recList(4,L). L = [19, 9, 5, 2] false
!
необходимо, потому что в противном случае, после первого решения, если вы нажмете больше, вычисление никогда не закончится. ТакжеX1 #> 0
иX2 #> 0
необходимы, потому что в противном случае вы получите ошибкуout of local stack
.