2016-10-21 29 views
2

特に私は、次のタイプの問題を解決するための最良の方法を決定しようとしています。論理プログラミングで何度も更新を処理する必要がありますか?

私が興味を持っている例は、Mitchell's Machine Learningの4つのトレーニング例に適用されたfind-sアルゴリズムです。

基本的な考え方は、各訓練例xと仮説hについて、hをより一般的にすることによってxを組み入れたかどうかを決定することです。トレーニングセットの各xについてhをh 'に写像する必要があります。私が抱えている問題は、これを論理プログラミング言語で最善の方法に接近させる方法です。私は、計画に埋め込まれた大まかにプロローグであるミニカンレンを使用しています。

各h 'を計算した後、私は設定する必要があります!それをグローバル変数hに変換し、次のトレーニング例xに進みます。以下のコードは、プログラムの主要部分です。

(define h '(0 0 0 0 0 0)) 

(define seto 
    (lambda (x) 
    (project (x) 
      (lambda (s) (set! h x) (succeed s))))) 

(run* (q) 
    (fresh (x h0 h1) 
      (trainingo x) 
      (== h h0) 
      (find-so h0 x h1) 
      (seto h1) 
      (== h1 q))) 

hはグローバル変数であり、瀬戸は(見つける-SO)のfind-Sアルゴリズムを使用してH0及びXトレーニング例から次の計算であるという仮説H1と時間を変異します。それはアサート(「仮説」(H))に(と思う)と同等になりプロローグで

各トレーニング例の後にXが(以前のものを上書き)と(「仮説」(H))後退を呼び出しますがすべてのトレーニングの例が適用された後。

もう一度私の質問は、これらの問題を解決するための最良のアプローチ(副作用による)かどうかです。

編集: 私は彼のcommentと一緒に@mat答えを受け入れました。要約すると、私は訓練の例をリストとして扱い、空リストに入るまでそのリストの前方再帰を使用する必要がありました。私が立ち往生していたのは、バックトラックの一環としてトレーニングの例を持つことでしたが、次の仮説を見つけるのではなく、空になるまで繰り返すことができます。

+0

あなたは正確にあなたが副作用を経由してこれをしたい理由を説明する必要があります。 @matの答えは、なぜこれに副作用が必要ではないのかを説明しています。 –

+0

ちなみに、Prologライブラリのコードには、効率の理由から副作用を使用した例があります。 [このコードはSWI-Prologのライブラリ(集約)](http://eu.swi-prolog.org/pldoc/doc_for?object=aggregate_all/3)を参照してください。いずれにしても、 'nb_ *'ファミリーの述語を使用することになります。ここで、「nb」は「バックトラック不可」を表します。 –

+0

私はこれを@matのコメントとして述べました: "私は次の仮説を得た後、次の訓練の例に戻った後に次の仮説を失いました。可能であれば、これを解決するために副作用を使用してください。 –

答えて

3

あなたの意見はと思われるかもしれませんassertz/0retract/1でグローバルアップデートをシミュレートしてください。あなたがそれを行う場合

しかし、主要 があるがを欠点この 方法:

  • グローバル状態を使用するには、あなたの述語分離でをテストとを使用してからあなたを防ぐことができます。
  • 破壊的な更新を使用すると、という方向で述語を使用できなくなります。
  • グローバル状態の微妙で暗黙的な依存関係により、述語の変更が非常にエラー になり易いになります。これらの状態の変化をシミュレートする

宣言型ソリューションは 状態関係の観点で考えることです。もし仮説H1を計算するH0を使用する場合、例えば

、その後、H0と  H1、およびおそらく他のパラメータとの関係として、これを表現することができます。そのような述語ががすべての方向にと—理想的— 実行を読むことができることを

  • hypothesis_next(H0, H1)
  • algorithm_hypothesis_next(A, H0, H1)
  • parameters_hypothesis_next(Ps, H0, H1)
  • など

注:のような述語について考えてみて!合計で

、溶液全体はあなたのケースで 仮説シーケンスとしてモデル化される:

H0&RIGHTARROW。 H1; H2; … → H

より多くの情報とポインタについては、密接に関連して質問を参照してください。

How to avoid using assert and retractall in Prolog to implement global (or state) variables

+0

ありがとう!しかし、問題は、次の仮説を得た後、次のトレーニングの例に戻って**私は次の仮説を失いました。可能であれば、これを解決するために副作用を使用したくありません。 –

+1

これに対する解決策は、**前方回帰**によるバックトラックを置き換えることです。あなたの仮説「H0」を改良するための訓練例が「Es」であるとします。 'examples_h0_h([]、H、H).'(例がない場合、最終仮説は初期仮説と同じです)と' examples_h0_h([E | Es ]、H0、H):hypothesis_next(E、H0、H1)、examples_h0_h(Es、H1、H).'で、各例で仮説を段階的に洗練する。このパターンはPrologではかなり頻繁に発生するため、 'foldl(hypothesis_next、Es、H0、H)'というメタ述語が 'foldl/4'と呼ばれます。 – mat

関連する問題