2016-03-28 5 views
9

instancesがあります。再帰的述部は、述部が双方向に変わるという利点を持ってCLP(FD)化できます。この方法の限界は何ですか?例えば以下computation CLP(FD)が-fiedができる:フィボナッチルーカス数の同時再帰CLP(FD)の可能性

Fn: n-th Fibonacci Number 
Ln: n-th Lucas Number (starting with 2) 

この倍加再帰ステップで:

F2n = Fn*Ln 
L2n = (5*Fn^2+Ln^2)//2 

そして、この増分再帰ステップ:

Fn+1 = (Fn+Ln)//2 
Ln+1 = (5*Fn+Ln)//2 

従来プロローグrealizationすでにnからFnまで働いています。これは高速再帰を維持すると同時に双方向的にするCLP(FD)プログラムに変えることができますか?たとえば、Fn = 377のインデックスnを計算しますか?はいの場合はどうですか?なぜそうならないのでしょうか?

bye

+0

fibluc/3はca.フィブス/ 2より20%速い。そのフィブスを行う必要があります/ 2はcall/nとプログラミングスティーンのようなテキストブックを使用しています。あなたの答えのコメントを見てください。しかし、どちらのアルゴリズムでも同じCLP(FD)の問題に遭遇するでしょう。 –

+0

ここで私はより良く見えるようになりましたが、これは違う服で同じアルゴリズムであるようです。私は私の答えを削除します。 –

+0

@Borisあなたのfib/2は本当に異なっていたと思います。途中でLucas Numbersを生成しないFibonacci Niumbersのよく知られているアルゴリズムです。こちらもご覧ください:https://en.wikipedia.org/wiki/Fibonacci_number#Matrix_formしかし、倍増と増分を使うことで似ていました。 –

答えて

4

はい、値を制約することによって実行できます。また、解決策を得るために必須ではありませんが、末尾再帰する再帰を移動することができます。

fibluc(0, 0, 2). 
fibluc(1, 1, 1). 
fibluc(N, F, L) :- 
    N in 2..1000,  % Pick a reasonable value here for 1000 
    [F, L] ins 1..sup, 
    N rem 2 #= 1, 
    M #= N-1, 
    F #= (F1 + L1) // 2, 
    L #= (5*F1 + L1) // 2, 
    fibluc(M, F1, L1). 
fibluc(N, F, L) :- 
    N in 2..1000,  % Pick a reasonable value here for 1000 
    [F, L] ins 1..sup, 
    N rem 2 #= 0, 
    M #= N // 2, 
    F #= F1 * L1, 
    L #= (5*F1*F1 + L1*L1) // 2, 
    fibluc(M, F1, L1). 

が得られます:

?- fibluc(10, X, Y). 
X = 55, 
Y = 123 ; 
false. 

?- fibluc(N, 55, Y). 
N = 10, 
Y = 123 ; 
false. 

?- fibluc(N, X, 123). 
N = 10, 
X = 55 ; 
false. 

?- fibluc(N, 55, 123). 
N = 10 ; 
false. 

?- fibluc(N, 55, 125). 
false. 

?- fibluc(N, X, Y). 
N = X, X = 0, 
Y = 2 ; 
N = X, X = Y, Y = 1 ; 
N = 3, 
X = 2, 
Y = 4 ; 
N = 7, 
X = 13, 
Y = 29 ; 
N = 15, 
X = 610, 
Y = 1364 ; 
N = 31, 
X = 1346269, 
Y = 3010349 ; 
N = 63, 
X = 6557470319842, 
Y = 14662949395604 ; 
... 

これはNときの増加値の結果を生成するように変更することができNはインスタンス化されていません。
はここでLinuxでSWI Prologの7.1.33で実行するタイミング、複合クエリの例、です:

?- time((fibluc(100, X, Y), fibluc(N, X, Z))). 
% 11,337,988 inferences, 3.092 CPU in 3.100 seconds (100% CPU, 3666357 Lips) 
X = 354224848179261915075, 
Y = Z, Z = 792070839848372253127, 
N = 100 ; 
% 1,593,620 inferences, 0.466 CPU in 0.468 seconds (100% CPU, 3417800 Lips) 
false. 

?- 

上記と同じコードと同じ化合物のクエリでSWI Prologの7.2.3を使用して、コードが消えません非常に長い時間です。私は少なくとも15分待っていた。それは今でもまだ実行中です...私は朝にそれを確認するかもしれません。 :)

私は、しかし、戻って次のように元のコードがそれを持っていた場所への再帰呼び出しを移動するために上記のコードを再整理しました:この場合

fibluc(0, 0, 2). 
fibluc(1, 1, 1). 
fibluc(N, F, L) :- 
    N in 2..1000,  % Pick a reasonable value here for 1000 
    [F, L] ins 1..sup, 
    N rem 2 #= 1, 
    M #= N-1, 
    fibluc(M, F1, L1), 
    F #= (F1 + L1) // 2, 
    L #= (5*F1 + L1) // 2. 
fibluc(N, F, L) :- 
    N in 2..1000,  % Pick a reasonable value here for 1000 
    [F, L] ins 1..sup, 
    N rem 2 #= 0, 
    M #= N // 2, 
    fibluc(M, F1, L1), 
    F #= F1 * L1, 
    L #= (5*F1*F1 + L1*L1) // 2. 

を、良好な結果が返さ:

​​

CLP(FD)のパフォーマンスは、さまざまなPrologインタープリタ間で大きく異なる可能性があることに注意してください。興味深いことに、SWI Prologでは、テール再帰的ケースを処理する機能がバージョン7.1.33で一時的に存在していました。

+0

@ j4nbur53 Prologインタープリタはあなたが使っていますか? SWI Prologにおいて、クエリ「?-fluluc(100、X、Y)、fibluc(N、X、Z)」。'は数秒で解決策を返します(私の更新された答えを見てください)。通訳者の非効率的なCLP(FD)の実装が原因でパフォーマンスが低下する可能性があります。 'sup 'はかなり大きいです。結果がオーバーフローする前に最大の「N」が何であるかわからない。あなたが見ているパフォーマンスの違いは、似たような問題の経験と一貫していますが。 'F'と' L'の制約はおそらくそれに寄与するでしょう。 – lurker

+0

以前のSWIのバージョンでは、 '(//)/ 2'の代わりに'(/)/ 2'を使用して、CLP(FD)式のフロア区切りを表すことができます。さまざまな議論の異なるスピードは、発生する整数とドメインの境界の素数性、除算性などの代数的性質に起因する伝播の違いによるものである可能性があります。 SWI-Prologでは、 'sup'は実際の無限大を意味します。その境界を超えることはできず、数値が大きすぎる場合はメモリが不足するだけです。これは、グローバルスタックの最大サイズと使用可能なRAMによって異なります。 – mat

+0

私は暗い人の質問に取り組んでいました。 – mat

関連する問題