2

Prolog を「学習」したばかりで、関数の入力と出力が何なのかよくわかりません。

例えば

concatenate([X|L1], L2, [X|L3]) = concatenate (L1,L2,L3).
concatenate([],L,L).

どういう意味ですか?

If I write 
?- concatenate(X,[2,Y],[1,1,1,2,3]) 

戻ります

X=[1,1,1],
Y=3.

つまり、3 番目のパラメーターは 1 番目と 2 番目のパラメーターを連結したものですが、関数の宣言を読むことでこれを知るにはどうすればよいでしょうか? ありがとう

4

3 に答える 3

5

すでに優れた2つの回答を補足するだけです...

Prolog では、パラメーターの入力と出力を持つ "関数" としてではなく (実際にはそのように動作しますが)、ルールを定義し、変数パラメーター (インスタンス化されていない変数) をインスタンス化しようとする "述語" として考えます。ルールを真にするような方法。このプロセスでは、解決策がまったく得られない場合もあれば、1 つの解決策が得られる場合もあれば、多くの解決策が得られる場合もあります。すべての解決策が得られます。インスタンス化されていない変数のすべての組み合わせに対して、すべての述語がこの「完全な機能」を提供するわけではありません。または、インスタンス化されていない変数が多すぎると、ソリューションを提供することが論理的に非現実的になります。これらの状況のいずれかでパラメーターの動作を決定するもの、および述語に解決策があるかどうかは、述語のロジックであり、入力または出力の正式な宣言ではありません。

与えられた例を見てみましょうconcatenate(注: これらには GNU Prolog を使用しています)。述語concatenate(L1, L2, L3)が意味するのは、「L1 と L2 を (その順序で) 連結すると L3 が得られる」ということです。これは、「L1 と L2 が与えられた場合、L3 でそれらの連結を提供する」と言うよりも一般的であり、特定の入力と出力を意味します。

だから私が入力した場合:

concatenate( [1,2], [3,4], L3 ).

私は得る:

L3 = [1,2,3,4]

(1 ms) yes
| ?-

これは、プロローグが、示されている のインスタンス化を使用して、述語に対する 1 つの解を見つけたことを意味しますL3。これを入力することもできます:

concatenate( L1, [3,4], [1,2,3,4] ).

そして、私は得るでしょう:

L1 = [1,2]

(1 ms) yes
| ?-

これは、プロローグが、示されている のインスタンス化を使用して、述語に対する 1 つの解を見つけたことを意味しますL1。同様に、入力した場合、concatenate( [1,2], L2, [1,2,3,4] )1 つの解決策が得られますL2 = [3,4]

もっと面白いことを試してみましょう:

concatenate( L1, L2, [1,2,3,4] ).

Prolog はこれに対する解決策を見つけますが、インスタンス化されていない変数を 2 つ用意しました。したがって、解決策には次の可能性が含まれます。

L1 = [1,2,3,4]
L2 = [] ? ;

L1 = [1,2,3]
L2 = [4] ? ;

L1 = [1,2]
L2 = [3,4] ? ;

L1 = [1]
L2 = [2,3,4] ? ;

L1 = []
L1 = [1,2,3,4] ? ;

(1 ms) yes
| ?-

これを試してみましょう:

concatenate( [1,2], L2, L3 ).

私は得る:

L3 = [1,2|L2]

| ?-

この場合、L2andの可能性L3は無限であるため、プロローグは一般的な解決策を示しています。

あなたの例でconcatenate( X, [2,Y], [1,1,1,2,3] )は、同じ考え方が当てはまります。Prolog は、「X を [2,Y] と連結すると [1,1,1,2,3] が得られる」という条件を満たすXandのインスタンス化を見つけようとします。[2,Y] は最初の要素と 2 番目の要素を持つリストです。要素。この場合、あなたが示すように、解決策は1つしかありません。Y2Y

このテーマのバリエーションとして、@DrH が説明するリストの概念を使用すると、次のようになります。

concatenate( X, [2|Y], [1,1,1,2,3] ).

と が得られX = [1,1,1]ますY = [3]。これを行った場合は次のことに注意してください。

concatenate( X, [2,Y], [1,1,1,2,3,4] ).

Yここでは がリストではなくアトムとして示されているため (カンマ構文のため)、「いいえ」(解決策なし)が返されます。言い換えれば、[2,Y]あらゆる可能性で連結されたときに、Xwill yieldのように見える 2 つの要素リストはありません[1,1,1,2,3,4]。しかし、これを行った場合:

concatenate( X, [2|Y], [1,1,1,2,3,4] ).

インスタンス化されていないものをリストの末尾として示しているため、それ自体がリストであり、単なるアトムではありません (X = [1,1,1]構文を使用)。Y = [3,4]Y|

@WillNess が指摘しているように、特定の述語のドキュメントでは、特定の変数をインスタンス化しないままにしておくと、述語の動作を期待する必要があることがわかります。適切に作成されたプロローグ述語は、適切に作成されていないものやより制限的なものよりも、「期待または要求することを実行する」可能性が高くなります。それは非常に有用な目的を果たす可能性があるため、より制限された述語を「悪い」ものにするわけではありません。それはそれほど役に立ちません。独自のプロローグ述語を作成するときは、これらのことを考慮してください。

プロローグは囲碁のようなものです。いくつかの単純なルールですが、多くの興味深い可能性があります。

于 2013-07-23T13:33:05.223 に答える
3

述語の各引数について、何が期待されるかを説明したコメントが必要です: 事前に設定されている (入力として使用できる)、自由である (まだ設定されていないため、出力に使用される)、または設定なし (したがって、両方可能です)。

SWI Prolog-4.1 Notation of Predicate Descriptionsのドキュメントを参照してください。彼らは使用します

  • +完全にインスタンス化された引数
  • -引数はアンバインドする必要があり、出力に使用されます
  • ?正しい型の部分的にインスタンス化された引数 (インスタンス化されていない変数は、任意の型の部分用語であることに注意してください)。

その他のいくつかの高度なオプション。

例のようにソースコードが単純な場合、どれがどれであるかが自明であると見なすことができます。

于 2013-07-23T11:47:08.063 に答える
1
concatenate([X|L1], L2, [X|L3]) :-
    concatenate(L1, L2, L3).

まず、Prolog のリストは head (ここではX) と tail (残りのリストは hereL1L3) で構成されます。したがって、この述語は、最初の要素がXであるリストがあることを示しています。これを と連結すると、最初の要素が であり、末尾が someL2であるリストが得られます。この述語が真であるためには、述語が失敗しないことも必要です。つまり、最初のリストの残りを 2 番目のリストと連結でき、それらが 3 番目のリストになります。XL3concatenate(L1, L2, L3)

引数は入力変数または出力変数のいずれかになる可能性があるため、この述語を未知の変数で呼び出すか、3 つのリストがある場合は、他の 2 つを連結してそのうちの 1 つを作成できるかどうかを確認できます。

2 番目の述語concatenate([], L, L)は、最初のリストが空の場合、連結の結果が 2 番目のリストになることを示します。

ありのままL1に。[1, 2, 3]_ L2_ [4, 5, 6]述語を呼び出して、内部で何が起こるか見てみましょう。

concatenate(L1, L2, L3).
concatenate([1, 2, 3], [4, 5, 6], L3).    // First predicate can be matched
concatenate([1 | [2, 3]], [4, 5, 6], [1 | A1]).    // Now [2, 3] is L1 and A1 is the current L3

concatenate([2, 3], [4, 5, 6], A1).    // First predicate can be matched
concatenate([2 | [3]], [4, 5, 6], [2 | A2]).    // Now [3] is L1 and A2 is L3

concatenate([3], [4, 5, 6], A2).    // First predicate can be matched
concatenate([3 | []], [4, 5, 6], [3 | A3]).    // Now [] is L1 and A3 is L3

concatenate([], [4, 5, 6], A3).    // Second predicate can be matched
concatename([], [4, 5, 6], [4, 5, 6]).

本体のない述語である終了条件があります。次に、逆方向に進みます (これはバックトラッキングと呼ばれ、探索空間で逆方向に進みます)。A* 変数を結果に置き換えましょう。

concatenate([], [4, 5, 6], [4, 5, 6]).

concatenate([3 | []], [4, 5, 6], [3 | [4, 5, 6]]).

concatenate([3], [4, 5, 6], [3, 4, 5, 6]).

concatenate([2 | [3]], [4, 5, 6], [2 | [3, 4, 5, 6]]).

concatenate([2, 3], [4, 5, 6], [2, 3, 4, 5, 6]).

concatenate([1 | [2, 3]], [4, 5, 6], [1 | [2, 3, 4, 5, 6]]).

concatenate([1, 2, 3], [4, 5, 6], [1, 2, 3, 4, 5, 6]).
于 2013-07-23T11:26:25.413 に答える