web-dev-qa-db-ja.com

ロジックプログラミングに関して、PrologとminiKanrenの主な技術的な違いは何ですか?

論理プログラミングを読みたいとき、私はいつもそれを行うための2つの「主な」方法につまずきます。

  • miniKanrenThe Reasoned Schemer で導入されたミニ言語で、 core.logic により現在人気があります=。
  • Prolog、最初の「大きな」論理プログラミング言語。

私が今興味を持っていること:この2つの主な技術的な違いは何ですか?アプローチと実装は非常に似ていますか、それともロジックプログラミングに対してまったく異なるアプローチを取っていますか?数学のどの分野から来たのか、そして理論的基礎は何ですか?

111
Profpatsch

まず、あなたの素晴らしいpw0n1eアイコンをcompめましょう。

これは、miniKanrenとPrologの両方のバリエーションが非常に多いため、答えるのが難しい質問です。 miniKanrenとPrologは実際には言語のファミリーであるため、機能を比較したり、実際の使用方法を比較したりすることは困難です。このため、これから説明するすべてを慎重に行ってください:Prologが深さ優先検索を使用すると言う場合、多くのProlog実装が他の検索戦略をサポートし、代替検索戦略もメタでエンコードできることに注意してください-通訳レベル。それでも、miniKanrenとPrologには異なる設計哲学があり、異なるトレードオフがあります。

Prologは、シンボリック人工知能プログラミングの2つの古典的な言語の1つです(もう1つの古典的な言語はLISPです)。 Prologは、宣言的知識が1次論理でエンコードされる記号ルールベースのシステムの実装に優れています。この言語は、これらのタイプのアプリケーションの表現力と効率のために最適化されていますが、時には論理的な純度が犠牲になります。たとえば、デフォルトでは、Prologは統一で「発生チェック」を使用しません。数学/論理の観点から見ると、このバージョンの統一は間違っています。ただし、発生チェックは高価であり、ほとんどの場合、発生チェックの欠如は問題ではありません。これは、Prologが深さ優先検索を使用し、カット(!)を使用してバックトラックを制御するのと同様に、非常に実用的な設計上の決定です。 1970年代のハードウェアで実行する場合、これらの決定は絶対に必要であり、今日では大きな問題に取り組む場合や、巨大な(多くの場合無限大!)サーチスペースを扱う場合に非常に役立ちます。

Prologは、カット、assertおよびretractisを使用した算術変数の投影など、多くの「余分な論理」または「非論理」機能をサポートしています。これらの機能の多くは、複雑な制御フローを簡単に表現し、Prologのグローバルな事実データベースを操作することを容易にします。 Prologの非常に興味深い機能の1つは、Prologコード自体が事実のグローバルデータベースに格納され、実行時にクエリを実行できることです。これにより、解釈中のPrologコードの動作を変更するメタインタープリターを作成するのは簡単です。たとえば、検索順序を変更するメタインタープリターを使用して、Prologで幅優先検索をエンコードすることができます。これは非常に強力な手法であり、Prolog以外ではあまり知られていません。 「The Art of Prolog」では、この手法について詳しく説明しています。

Prolog実装の改善に多大な努力が払われましたが、そのほとんどはWarren Abstract Machine(WAM)に基づいています。 WAMは、値が論理変数に破壊的に割り当てられる副作用モデルを使用します。これらの副作用は、バックトラック時に元に戻されます。 WAMの指示を拡張することにより、多くの機能をPrologに追加できます。このアプローチの欠点の1つは、WAMをしっかり理解していないと、Prologの実装に関する論文を読むのが難しい場合があることです。一方、Prologの実装者には、実装の問題を議論するための共通のモデルがあります。並行してプロローグで多くの研究が行われ、1990年代にアンドラプロローグで頂点に達しました。少なくともこれらのアイデアのいくつかは、Ciao Prologに残っています。 (Ciao Prologは興味深いアイデアでいっぱいで、その多くはProlog標準をはるかに超えています。)

プロローグには、統一に基づいた美しい「パターンマッチング」スタイルの構文があり、非常に簡潔なプログラムになります。 Lispersがs式を好むように、プロロージャーは構文を好む。 Prologには、標準述語の大規模なライブラリもあります。 WAMの高速化に取り組んできたすべてのエンジニアリングにより、非常に有能で成熟したProlog実装があります。その結果、多くの大規模な知識ベースのシステムは完全にPrologで記述されています。

miniKanrenは最小限のロジックプログラミング言語として設計されており、小さく、簡単に理解でき、簡単にハッキングできる実装を備えています。 miniKanrenは元々Schemeに組み込まれており、過去10年間で他の多くのホスト言語に移植されてきました。最も人気のあるminiKanren実装は、Clojureの「core.logic」です。これには、多くのPrologのような拡張機能と多数の最適化が含まれています。最近、miniKanren実装のコアがさらに簡素化され、「microKanren」と呼ばれる小さな「マイクロカーネル」が生まれました。その後、miniKanrenをこのmicroKanrenコアの上に実装できます。 microKanrenまたはminiKanrenを新しいホスト言語に移植することは、miniKanrenを学習するプログラマーの標準的な演習となっています。その結果、最も人気のある高水準言語には、少なくとも1つのminiKanrenまたはmicroKanrenの実装があります。

MiniKanrenおよびmicroKanrenの標準実装には、単一の例外を除いて、突然変異やその他の副作用は含まれていません。miniKanrenの一部のバージョンは、論理変数の比較にポインター等価性を使用します。私はこれを「良性効果」と考えていますが、多くの実装では、実装にカウンタを渡すことでこの効果さえも回避しています。グローバルなファクトデータベースもありません。 miniKanrenの実装哲学は、関数型プログラミングに触発されています。突然変異と効果は避け、すべての言語構造は語彙の範囲を尊重する必要があります。実装を注意深く見ると、いくつかのモナドを見つけることができます。検索の実装は、レイジーストリームを組み合わせて操作することに基づいており、再びミューテーションを使用しません。これらの実装の選択は、Prologとは非常に異なるトレードオフにつながります。 Prologでは、変数のルックアップは一定時間ですが、バックトラッキングには副作用を取り消す必要があります。 miniKanrenでは、変数検索はより高価ですが、バックトラッキングは「無料」です。実際、miniKanrenには、ストリームの処理方法に起因するバックトラックはありません。

MiniKanren実装の興味深い側面の1つは、コードが本質的にスレッドセーフであり、少なくとも理論的には、簡単に並列化できることです。もちろん、各スレッドまたはプロセスにオーバーヘッドを埋め合わせるのに十分な作業を与える必要があるため、コードを並列化せずにslowerにするのは簡単ではありません並列化。それでも、これはminiKanren実装の領域であり、より多くの注目と実験を期待しています。

miniKanrenは、統一の発生チェックを使用し、深さ優先検索の代わりに完全なインターリーブ検索を使用します。インターリーブ検索は、深さ優先の検索よりも多くのメモリを使用しますが、深さ優先の検索が永遠に発散/ループする場合には、答えを見つけることができます。 miniKanrendoesはいくつかの余分な論理演算子をサポートします---condacondu、およびproject例。 condaおよびconduを使用してPrologのカットをシミュレートでき、projectを使用して論理変数に関連付けられた値を取得できます。

condacondu、およびproject---の存在と、検索戦略を簡単に変更する機能---プログラマーは、組み込みPrologライクな言語としてminiKanrenを使用できます。これは、多くのPrologのような拡張機能を含むClojureの「core.logic」のユーザーに特に当てはまります。 miniKanrenのこの「実用的な」使用は、業界でのminiKanrenの使用の大部分を占めるようです。 ClojureまたはPythonまたはJavaScriptで記述された既存のアプリケーションに知識ベースの推論システムを追加したいプログラマーは、一般にPrologでアプリケーション全体を書き直すことに関心がありません。小さなロジックプログラミング言語をClojureまたはPythonははるかに魅力的です。埋め込みProlog実装は、おそらくこの目的で同様に機能します。おそらく、miniKanrenは、小さくて純粋なコアにより、埋め込みロジック言語として人気が高まっていると思います。実装、および「The Reasoned Schemer」の発行以降に発表された講演、ブログ投稿、チュートリアル、およびその他の教材。

MiniKanrenは、Prologに似た実用的な組み込みロジックプログラミング言語としての使用に加えて、「リレーショナル」プログラミングの研究にも使用されています。つまり、数学関数ではなく数学関係として振る舞うプログラムを書くことです。たとえば、Schemeでは、append関数は2つのリストを追加し、新しいリストを返します。関数呼び出し(append '(a b c) '(d e))は、リスト(a b c d e)を返します。ただし、appendを2つの引数の関数としてではなく、3つの場所の関係として扱うこともできます。呼び出し(appendo '(a b c) '(d e) Z)はその後、論理変数Zをリスト(a b c d e)に関連付けます。もちろん、論理変数を他の位置に配置すると、事態はさらに面白くなります。呼び出し(appendo X '(d e) '(a b c d e))X(a b c)に関連付け、呼び出し(appendo X Y '(a b c d e))XYをリストのペアに関連付けます。 (a b c d e)と等しい。たとえば、X = (a b)およびY = (c d e)は、このような値のペアの1つです。 (appendo X Y Z)を記述することもできます。これは、XYに追加するなど、無限に多くのリストのトリプルZX、およびYを生成します。 Zを生成します。

appendのこのリレーショナルバージョンは、Prologで簡単に表現でき、多くのPrologチュートリアルで実際に示されています。実際には、より複雑なPrologプログラムは、カットなどの少なくともいくつかの余分な論理機能を使用する傾向があり、結果として生じるプログラムを関係として扱う能力を阻害します。対照的に、miniKanrenはこのスタイルのリレーショナルプログラミングをサポートするように明示的に設計されています。 miniKanrenの最新バージョンでは、シンボリック制約解決(symbolonumberoabsento、不等式制約、ノミナルロジックプログラミング)がサポートされており、自明でないプログラムを関係として簡単に記述できます。実際、私はminiKanrenの特別な論理機能を一切使用せず、すべてのminiKanrenプログラムを関係として作成します。最も興味深いリレーショナルプログラムは、Schemeのサブセットのリレーショナルインタープリターです。これらのインタープリターには、リスト(I love you)に評価される100万個のSchemeプログラムの生成や、クイン(自力で評価するプログラム)の生成など、多くの興味深い機能があります。

miniKanrenは、このリレーショナルスタイルのプログラミングを可能にするために多くのトレードオフを行います。これは、Prologが行うトレードオフとは非常に異なります。徐々にminiKanrenはより多くのシンボリック制約を追加し、シンボリック指向の制約論理プログラミング言語になりました。多くの場合、これらのシンボリック制約により、conduprojectなどの余分な論理演算子の使用を避けることが実用的になります。その他の場合、これらのシンボリック制約では不十分です。シンボリック制約に対するより良いサポートは、関係としてより大きくより複雑なプログラムをどのように書くかという幅広い質問とともに、miniKanrenの研究の1つのアクティブな領域です。

つまり、miniKanrenとPrologの両方に興味深い機能、実装、および使用法があり、両方の言語からアイデアを学ぶ価値があると思います。 Mercury、Curry、Gödelなど、他の非常に興味深いロジックプログラミング言語もあります。それぞれが独自のロジックプログラミングを取り入れています。

最後に、miniKanrenのリソースをいくつか紹介します。

MiniKanrenのメインWebサイト: http://minikanren.org/

Prologとの比較を含む、リレーショナルプログラミングとminiKanrenに関するインタビュー: http://www.infoq.com/interviews/byrd-relational-programming-minikanren

乾杯、

- 意志

260
William E. Byrd

暫定的な回答:

知る限り、「The Reasoned Schemer」は、Scheme-y構文および関数型プログラミングスタイルで基本的なロジックプログラミングを導入し、特にブール値「#t」に一定の目標「#u」(失敗)および「#s」(成功)を追加しました。 「および「#f」。 Prologと同じロジックプログラミングのアプローチを使用しました:統合およびバックトラッキング検索。週末に棚からその本を取り出す時間があるかどうかを確認します。数学の分岐は、制限された形式の1次論理、この場合はHorn節、および解決の不一致です。参照: 計算論理:過去の記憶と未来への挑戦 ジョン・アラン・ロビンソンおよび 論理プログラミングの初期 コールドスタートについてはロバート・コワルスキー。

4
David Tonhofer