2013-06-19 3 views
5

Prologでは、テンプレート(変数を含む構造体)を用意し、それに一連の制約を満たすことで問題を解決することがよくあります。簡単な例は次のようになります。Prologで一連の目標を達成する

go(T) :- 
    T = [_, _, _], 
    member(cat, T), 
    member(dog, T), 
    member(mouse, T). 

そして、実際には、制約のセットは、むしろ固定されている以外の何らかの方法で生成された、と私は順番に各制約を満たすように再帰的な述語を記述する必要がありますされています

go(T) :- 
    T = [_, _, _], 
    findall(A, animal(A), As), 
    % satisy member(A, T) for each A in As 
    fill_in_animals(T, As) 

fill_in_animals(T, []). 
fill_in_animals(T, [A|Rest]) :- 
    member(A, T), 
    fill_in_animals(T, Rest). 

私の質問はリスト関連の制約ではなく、上記のように比較的簡単なヘルパー述語に渡すリストとして、制約に対するパラメータさえも常に簡単に生成できるとは限りません。実際に私はヘルパーは、私が毎回、書き込みかなり不格好述語です見つける:

  1. テンプレート、制約のために使用されるいくつかのパラメータを(したがって、有用な値にテンプレートの変数を結合するための)受け入れを、それがどの制約にあるかを示すための変数とを含む。
  2. この繰り返しで満たすための制約を生成し、それをテンプレートに適用します。
  3. 残りの制約が満たされるように再帰的に自身を呼び出します。

私が探しているのは、findallなどの行に沿った述語です。これは、一連の目標を順番に満たします。何かのように:

% satisfyall(:Goal) 
% backtracks on Goal but keeps all bindings from each fully satisfied goal. 

satisfyall((animal(A), member(A, T))) 

私が探している答えはこの形式にする必要はありません。実際には、目標へのバックトラックとそれに起因するバインディングの各セットの維持との間に矛盾が存在する可能性があります。

私は自分の問題を説明して助けになるものが合理的であることを願っています。 (私に知らせていないならば)長い間巻き込まれた質問のために事前にお詫び!

更新(2年後)

私は後で今日それを試してみると私の質問を更新します!

私が試したのと同じ日に質問を更新するつもりはなかったことに注意してください。 ;-)

@CapelliCは正しい方向に私を操縦している、と私はかなりよく働くようでパターン発見しました:

?- Gs = [member(red),member(blue)], T = [_,_], foreach(member(G, Gs), call(G, T)). 
T = [red, blue] ; 
T = [blue, red] ; 
+2

[lambda.pl](http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/lambda.pl)助けることができるが、私はあなたがのfindAllと行くべきだと思います/ 3 – CapelliC

+0

ラムダがSWIに配布されていない特別な理由はありますか?私は 'use_module(library(lambda))'ができることを大切にしています! –

+0

@DanielLyons:私はこの同じ質問に答えようとしたときに、いくつかのダウンホートを得ました:) – CapelliC

答えて

1

あなたは確かに、動作するために行われた変更を元に戻すにはが必要です。 これはPrologアルゴリズムの核心であり、Prologの電源です。

また、より一般的な計算になると弱点になります。のように、副作用やループには必ずが含まれています。

私たちのルールを確定的なパスに沿って強制的に働かせる正しい方法を見つけることは、おそらくPrologが動作する方法ではないので難しいでしょう。

さて、今、哲学の暴言を停止する、のは、プロローグの達人たちが利用できるようにしているか見てみましょう:SWI-Prologはあなたがforeachを見つけるライブラリ(aggregate)を提供しています、私はあなたが後にしているものの多くを行う考えていること:

このような複雑な組み込みを勉強
?- foreach(animal(X), member(X,L)). 
L = [cat, dog, mouse|_G10698] . 

は、(ソースを検査するために、コンソールから?- edit(foreach).を使用してください)あなたの実装のためのいくつかのアイデアを与えることができます。

GeneratorとGoalが分かれていることに注意してください。あなたの質問では、彼らは絶望的です。もちろん、が必要ですを発電機部分にバックトラックすることができるのはもちろんです。

ところで、docページの小さなサンプルのリストを理解してみてください。これはdif/2によって非常に複雑ですが、再帰的述語を一般化できるようにするためには、バインディングの動作を把握する必要があります。

HTH

+0

遅い返事をおかけして申し訳ありません。私はあなたが私を正しい軌道に乗せたと思う。 – Edmund

3

あなたが質問に記述する状況を署名とは少し異なっていますあなたが与えたsatisfyall/1述語のfill_in_animalsの例に含まれるバックトラッキングはありません。少なくとも、流出する変数はgo/1ではありません。サブゴールの満足度には「プチバックトラック」があるかもしれませんが、バインディングをそのまま残しながら全体的な目標は失敗しません。

maplist/2を使用するのはおそらく役に立たない解決策です。

?- length(L, 3), maplist(animal, L). 
L = [cat, cat, cat] ; 
L = [cat, cat, dog] ; 
L = [cat, cat, mouse] ; 
L = [cat, dog, cat] ; 
... 
L = [mouse, mouse, dog] ; 
L = [mouse, mouse, mouse]. 

あなただけの1つの述語を追加することによって、マテリアライズド・データベースを使用するために行くことができます::

% just flips the arguments of member/2 
memberof(L, A) :- member(A, L). 

はその後、我々は仕事をするためにfindall/3を使用することができますたとえば、あなたの例では、この方法を達成することは容易です:

?- findall(A, animal(A), Animals), 
    length(L, 3), 
    maplist(memberof(Animals), L). 

Animals = [cat, dog, mouse], 
L = [cat, cat, cat] ; 
Animals = [cat, dog, mouse], 
L = [cat, cat, dog] ; 
Animals = [cat, dog, mouse], 
L = [cat, cat, mouse] ; 
... 
Animals = [cat, dog, mouse], 
L = [mouse, mouse, dog] ; 
Animals = [cat, dog, mouse], 
L = [mouse, mouse, mouse]. 

これは、なぜlambda.plが役立つかを明確にするはずです。あなたはヘルパー述語を必要としない、あなたは、単に書くことができます:

?- findall(A, animal(A), Animals), 
    length(L, 3), 
    maplist(\Animal^member(Animal, Animals), L). 

(未テスト)

あなたはバインディングとアンバインド変数を回避する上で本当に意図している場合、私はあなたが作成するつもりだと思いますSWI-Prologにはglobal variable facilityがあります。 asserta/retractがこの作業には不十分であることを漠然と思い出しています。

とは実質的に異なるsatisfyall/1の意味のある実装ではないように感じるほど、私はもっと気になりますが、私は間違っていると思っています。

+0

私はlambda.plに精通していないし、今まで馬術師に気づいていなかったが、マプリストは私のところへ行く途中で80%を得ているようだ。私は今日後でそれを試して、私の質問を更新します! – Edmund

+0

@hardmathや他の誰かが、あなたの残りの道を得る 'satisfallall/1'を思いつく方法を見て欲しいです。通常の統一プロセスに頼っているのではなく、テンプレート構造を直接利用する方法はありません。うまくいけば、他の人たちはより良い想像力を持ち、将来の道を見ることができます。 :) –

+0

'動物は'グローバルに宣言する必要があります: 'マプリスト(動物+ \動物^動物(動物、動物)、L)' – false

関連する問題