2017-02-21 10 views
2

factorary述語fact(N,F)があります。NまたはFまたはその両方が数値にバインドされています。Prolog factorial述語

例えば、私はfact(3,F)またはfact(N,6)を持つことができます。 ここに私の述語がありますが、実際にはどのように理解できません。私はtraceを使用しましたが、まだそれを理解することに問題があります。

fact(0,1). 
fact(N,F) :- 
     fact(N1,F1), 
     N is N1 + 1, 
     F is N * F1. 
+1

また、 'fact(3、F)'は 'fact(0、1)'と一致しないので(3と0は統一できないので)、Prologは次の句'fact(N、F)'と 'N = 3'を比較します。次に、最初の節で 'N1 = 0'と' F1 = 1'で出てくる 'fact(N1、F1)'をもう一度呼びます。解決策を見つけた後、それはより多くを見つけることを試み、終了せず、スタックオーバーフローを引き起こすことに注意してください。 – lurker

+1

私は不思議です:どのように動作しているかわからない場合、この述語を書く方法はどうでしたか? – lurker

+1

@lurker:それは非常に理解できます。別のバージョンがインスタンス化エラーを引き起こした可能性があります。 – false

答えて

4

あなたのプログラムをステップバイステップで調べて、何が起こっているのかを理解することができます。あなたは本当に非常に遅く、非常に信頼できません。あるいは、Prologに仕事の一部をさせてください。だから、プログラムを少し修正して、Prologがそれをどのように考えているかを見てみましょう。

これは私があなたのプログラムを見たときに私が見たものである - これは

fact(0,1) :- false. 
fact(N,F) :- 
     fact(N1,F1), false, 
     N is N1 + 1, 
     F is N * F1.

場合はこの断片が終了しますと呼ばれていますか?残っている目に見える部分を見てください! Nは先頭に1回しか出現しません。最初の引数には誰も関心がありません! Fと同じです。したがって、あなたが持っている引数にかかわらず、プログラムは終了しません。 あなたの元のプログラムも同様です。

明確ではないオリジナルのバージョンです。気をつけろ:

?- fact(29,F). 
F = 8841761993739701954543616000000 

最初はこれは良さそうに見えますが、あなたは(SPACEまたは;と)次の答えを求めるならば、あなたはループで終了します。悪いクエリは即座にループします:

?- fact(29,1). 
** LOOPS ** 

何が起こっているのかを正確に理解することなく、どのようにこれらの問題を見つけることができますか?これは何ですかfalseです。決して真実ではない目標。 fact(29,F), false.のように追加すると、美しい答えに気を取られることはありません。

なぜあなたはすべての算術を最後に置いたのですか?私はあなたが以前にいくつかのエラーを持っていたので、疑う。すべてのこのようなエラーを回避するための簡単な方法があります:

:- use_module(library(clpfd)). 

あなたは今is#=するのではなく、書き込み、およびあなたがN #>= 1のようないくつかの制限が必要です。私はあなたをそこに残すことができますか?