1

ルールを再度起動する前に、ルールが既に「起動」されているかどうかを確認する必要があります。つまり、新しいファクトをアサートする前に、前のループ反復で同じファクトが既にアサートされているかどうかを知る必要があります。

リストを使用しようとしましたが、私の問題にはあまり「友好的」ではないと思います。これを行うために他に何が使えますか?

4

1 に答える 1

1

上記のコメントを、もう少し詳しく説明するための回答として言い換えています。

ソリューションを生成した後に失敗する失敗駆動型ループを検討し、Prolog をバックトラックさせて他の可能性を探らせることができます。

failure_driven_loop(Info):- generate(Info,Term), fail. 
failure_driven_loop(Info). 

(例はPaul Brna の本からのものです)。この例Termでは、ソリューションを記録し、指定された のソリューションをgenerate/2生成しますInfo。2 番目の句は、すべてのソリューションが使い果たされたときにループを成功させるために必要です。

解決策が生成されると、最初の節は失敗し、実行は後戻りします。つまり、Prolog は の別の証明を見つけようとします。これには通常、それ自体または によって直接的または間接的に呼び出される述語の 1 つgenerate(Info,Term)に対するさまざまな節が含まれます。一度その句の 1 つを使用したことを確認したい場合は、同じ句を再利用しようとしないようにする必要があります。つまり、代わりにカットを追加する必要があります。generate/2generate/2generate/2

generate(Info,Term) :- solve_somehow(Info,Term).
generate(Info,Term) :- solve_in_some_other_way(Info,Term).

あなたは書くべきです

generate(Info,Term) :- solve_somehow(Info,Term), !.
generate(Info,Term) :- solve_in_some_other_way(Info,Term), !.

で見つかったソリューションは、generate/2で記録できますassert。@CapelliC が指摘したように、プログラムがバックトラックした場合、アサーションは元に戻されないため、失敗駆動ループはソリューションを保持します。

:- dynamic solution/1.

failure_driven_loop(Info):- generate(Info,Term), assert(solution(Term)), fail. 
failure_driven_loop(Info). 
于 2013-07-12T21:12:41.810 に答える