4

次の関数を使用してフィボナッチ数列を計算しようとしています。

fib(0,A,_,A).
fib(N,A,B,F) :-
    N1 is N-1, Sum is A+B, fib(N1, B, Sum, F).
fib(N, F) :- fib(N, 0, 1, F).

これは、次のように機能することを目的としています。

| ?- fib(20,Result).

Result = 6765 ? 

しかし、私がこれを試してみると、次のように文句を言います。

| ?- fib(What,6765).
uncaught exception: error(instantiation_error,(is)/2)

なぜこれが起こっているのか誰かが理解していますか?

4

3 に答える 3

4

2番目の節:

fib(N,A,B,F) :-
    N1 is N-1, Sum is A+B, fib(N1, B, Sum, F).

Nはデクリメントされる変数であり、次の呼び出しで:

fib(What, 6765).

変数はまだ定義されていないため、でインスタンス化エラーが発生しN1 is N - 1ます。

swiplでは、エラーが発生することもあります。

?- fib(W, 6765).
ERROR: fib/4: Arguments are not sufficiently instantiated
于 2012-12-24T13:00:36.773 に答える
3

エラーであることがわかったので、クエリに実際に答えることができるかどうかを知っていただけませんか。

どのように問題に取り組みますか?あなたの機能は大丈夫ですよね?正確には、これは関数であり、リレーションではないため、エラーが発生します。

それを解決するのは少し複雑ですが、CLPはそれを行うことができます!

CLP(FD)ドキュメント(ここで引用)からこの魅力的な例を参照してください

:- use_module(library(clpfd)).

n_factorial(0, 1).
n_factorial(N, F) :-
        N #> 0, N1 #= N - 1, F #= N * F1,
        n_factorial(N1, F1).

このようなものが必要ですが、フィボナッチの場合です。それがいかに簡単かをご覧ください。

:- [library(clpfd)].

fib(0,A,_,A).
fib(N,A,B,F) :-
    N #> 0,
    N1 #= N-1,
    Sum #= A+B,
    fib(N1, B, Sum, F).
fib(N, F) :- fib(N, 0, 1, F).

isつまり、 /2を/2に置き換える#=と、次のようになります。

?- fib(20,Result).
Result = 6765 .

?- fib(X,6765).
X = 20 ;
^C

最初の応答の後、プログラムがループすることに注意してください。あなたはそれを修正する方法を見ますか?または別の質問は価値があるかもしれません...

于 2012-12-24T17:30:51.510 に答える
0

より明確でより自然な述語の定義は次のようになります。

//The two base steps
fib1(0,0). 
fib1(1,1).
//the recursive step
fib1(N,F) :- 
        N >= 0, M is N-2, O is N-1, fib1(M,A), fib1(O,B), F is A+B.

これは、述語が1つしかない定義でもあります:fib / 2

于 2013-04-10T20:08:02.740 に答える