2

私はこの非常に単純な問題を抱えています:2つの文字列を連結し、次のように機能する、追加のProlog関数を実装するPrologプログラムを作成します。

  1. append([a、b]、[c、d]、X)。---> X = [a、b、c、d]
  2. append([a、b]、X、[a、b、c、d])。---> X = [c、d]
  3. append([a、b]、[X、d]、[a、b、c、d])。---> X = c
  4. append(X、Y、[a、b、c、d])。---> X=[]およびY=[a、b、c、d)

したがって、次の2つの解決策がありますが、宣言型の解釈が正しいかどうかはわかりません。

1)解決策1:

myappend1([],L,L).

myappend1([X|L1],L2,[X|L3]) :- myappend1(L1,L2,L3).

私はそれを次のように宣言的な方法で読むことができると思います:

事実は次のように述べています。最初のリスト(L1)が空で、2番目のリスト(L2)が空でない場合、L1*L2の連結がL2であることはTRUEです。

それが真実でないという事実は、最初のリストが空ではないことを意味します。したがって、最初のリストと2番目のリストの連結は、2番目のリストであるということは真実ではありません。

したがって、最初のリストをL1、2番目のリストをL2、3番目のリストをL3と呼ぶと、L3がL1とL2の連結である場合、ルールはTRUEと応答し、それ以外の場合はfalseと応答します。

このルールの宣言的な意味は次のとおりだと思います。ルールの本体が真の場合、ルールの先頭は真です。

  • 頭の中で、L1リストとL3リストから最初のX要素を抽出します(一致する場合は統合を試みます。一致しない場合は、3番目のリストが最初と2番目のリストの連結ではないことを意味します)
  • 本文では、X要素のない最初のリスト、2番目のリスト、およびL3リスト(連結を表す)の関数を呼び出します。

myappend1([]、L、L)という事実が実証されたベースケースに到達したとき。つまり、プログラムは前の過去にバックトラックを実行し、最初のリストのX要素が3番目のリストのX要素と統合されているため、この計算パスもTRUEであり、最初のアサーションに到達するまで戻ります。

これは正しい宣言型の解釈ですか?

2)2番目の解決策:

myappend2([],L,L).

myappend2(L1,L2,L3) :-  L1=[X|T],               % Dimostra questo predicato AND
                    L3=[X|L4],      % Dimostra questo predicato AND
            myappend2(T,L2,L4).     % Dimostra questa funzione

前のソリューションと同様に、事実は単純に次のように述べています。最初のリスト(L1)が空で、2番目のリスト(L2)が空でない場合、L1*L2の連結がL2であることはTRUEです。

それが真実でないという事実は、最初のリストが空ではないことを意味します。したがって、最初のリストと2番目のリストの連結は、2番目のリストであるということは真実ではありません。

事実が真でない場合、Prologはルールを呼び出し、このルールは次のことを意味します。ルールの本体が真の場合、ルールの先頭は真です。

この場合、私はそれを次のように読むことができます:

L1とL2の連結はL3であり、次のことが当てはまる場合はTRUEです。

  • L1の現在の最初のX要素は、連結リストの現在の最初の要素と統合され、myappend2は最初のサブリストL2と3番目のサブリストで呼び出されます。

それが正しいか?

私にとって、宣言的な方法で推論するのはとても難しいです:-(

4

2 に答える 2

2

述語の宣言的な意味を理解しようとすると、次のように尋ねられます。この述語はどのソリューションに当てはまりますか?

Prologの1節は、一連のソリューションに独立して貢献します。したがって、条項間の接続を確立するには、さらに精査する必要があります。そうでないいくつかの仮定をすることは非常に簡単です:

myappend1([],L,L).それが真実でない という事実は、最初のリストが空ではないことを意味します...

目標を考えてみましょうmyappend1([],[],[a]).。事実は当てはまりませんが、最初のリストは空です。ここでは、句の意味を操作可能にしようとしています。プログラミング言語の大部分は、何かが段階的にどのように発生するかを想像することによってのみ理解できるため、これを行うのは非常に魅力的です。Prologの難しさは、手続き的な側面を完全に無視することなく、そのような詳細を無視しようとすることにあります。

myappend1([X|L1],L2,[X|L3]) :- myappend1(L1,L2,L3).

ルール、特に再帰ルールを読むに:-は、1970年代の←のレンダリングであるルールを確認すると便利です。つまり、矢印ですが、右から左に向かっています。したがって、このルールは、右側から始めて、次のように読むことができます。

それmyappend(L1,L2,L3)が成り立つならば、今度は左側へのクロス:-オーバーもmyappend([X|L1],L2,[X|L3])成り立ちます。

時々、そのようなルールを読むためのさらに良い方法は、頭を完全に覆って尋ねることです

??? :- myappend1(L1,L2,L3).

私はこれから何を結論付けることができるかを保持するいくつかL1を知っていると仮定しますか?何か面白いことはありますか?これらの3つの値から簡単に構築できる関連するものはありますか?L2L3myappend1(L1,L2,L3).

あなたが言うかもしれないので、これは最初は少し反抗的なものです:しかし、どうすればそのようなものが存在することを知ることができますか?まあ、あなたはしません。あなたはそれが存在すると仮定しているだけです。それが決して存在しない場合、あなたはその結論を出すことができなくなります。

多くの人がルールを左から右に読み込もうとしますが、Prologが実際にルールを左から右に実行している間、それらがカバーする意味は結論の方向に進むことで理解しやすくなります。Prologがルールを左から右に実行するとき、これがうまくいくかどうかはわかりません。したがって、処刑は完全に投機的な性質のものである可能性があります。考えてみてくださいappend(L1,[z],[a,b,c,d,e])。ここで、Prologはリストの各要素にこのルールを適用します。しかし、そのようなアプリケーションはすべて無駄です。つまり、最終的には失敗します。


ファインプリント

1実際には、Prologの純粋な単調なサブセットです。

于 2013-03-19T19:48:38.253 に答える
2

前回と同様に、コードに存在しない制限を追加しています。それについて悪く感じないでください、Prologは非常に異なっており、それに慣れるのに時間がかかります。

はじめましょう。

append([], L, L).

あなたが言った:

最初のリスト(L1)が空で、2番目のリスト(L2)が空でない場合、L1*L2の連結がL2であることはTRUEです。

実際、このルールは、L2が空であるかどうか、またはリストでさえあるかどうかについては何も述べていません。それは単に、他の何かに追加された空のリストが他の何かであると言っています。観察:

?- append([], foo, X).
X = foo.

ここでの宣言型の読みは、「Lに追加された空のリストはLです」です。

それが真実でないという事実は、最初のリストが空ではないことを意味します。したがって、最初のリストと2番目のリストの連結は、2番目のリストであるということは真実ではありません。

はい、これは正しいですが、Prologはそれを体の奥深くまで調べていません。「最初のリストは空ではないので、このルールは一致しません。次に進みます」とだけ書かれています。

次のルール:

myappend1([X|L1], L2, [X|L3]) :- myappend1(L1,L2,L3).

あなたの解説は私には過度に複雑に思えます。このルールは、「リストL1からL2のmyappend1がL3の場合、L2へのリスト[Xの後にL1]のmyappend1はリスト[Xの後にL3]です」と言います。ただし、この読み物の結果は、あなたが説明したとおりです。

したがって、最初のバージョンで何が起こっているかについてのあなたの理解は正しいです。

2番目の解決策は、機械的には最初の解決策とまったく同じです。唯一の違いは、統合を句の先頭から本文に移動したことです。このバージョンは、読者のために余分な作業を作成するだけなので、私の目には明らかに劣っています。

これまでのところ、あなたが抱えている問題は、宣言型の推論がPrologの計算エンジンと密接に結びついていることだと思います。私が提供したもののようなより純粋な宣言型の読みは、より単純で、Prologが言っていることに似ています(そしてそれがどのように評価されるかとはあまり関係がありません)。

これらの概念を分離するには練習が必要ですが、それはあなたがより良くなるのに役立つと思います(明らかにそれはあなたが心配していることです)。それまでの間、ここに来て、混乱したときに行ってきたように助けを求めることには何の問題もありません。:)

私がもっと助けることができるかどうか私に知らせてください!

于 2013-03-19T18:58:11.230 に答える