3

次のナレッジ ベースがある場合、X が既に父親であると判断されている場合に、プロローグが X が母親でもあるかどうかを「チェック」しようとしないように、parent_of 用語にカットを追加するにはどうすればよいですか?

father_of(max,john).
father_of(max,james).
father_of(max,gabe).
mother_of(june,john).
mother_of(june,james).

parent_of(X,Y) :- father_of(X,Y).
parent_of(X,Y) :- mother_of(X,Y).

たとえば、私は欲しい:

parent_of(max,Y) は次のようになります: Y=john, Y=james, Y=gabe

parent_of(jun,Y) は次のようになります: Y=john, Y=james

最初のものについては、プロローグが max が Mother_of であるかどうかをチェックしようとさえしたくありません。

私はすでに次のような多くの組み合わせを試しました:

parent_of(X,Y) :- father_of(X,Y),!.  <-- fixes an X and Y and thus will list only Y=john
parent_of(X,Y) :- !,father_of(X,Y). <-- works for parent_of(max,Y) but not parent_of(jane)

これは可能ですか?

4

2 に答える 2

1

このような最適化を行うのは非常に注意が必要です。そして、Prologは最適化なしでそのような問題でかなり実行しています。

ただし、原則として、プログラムにカットを設定するだけではなく、事前にあらゆる種類のテストを実行する必要があります。これらのテストは、削除しようとしているオーバーヘッドよりも簡単に費用がかかると思います。これが試みです。正直なところ、最初に純粋なPrologを学ぶべきなので、私はあまり気分が良くありません。

したがって、次の解決策はないと想定します。?- father_of(P,_), mother_of(P,_).

parent_of(F、C):-
   (atom(F)、\ + \ + Father_of(F、_)->!
   ; true
   )、
   Father_of(F、C)。
parent_of(M、C):-
   mother_of(M、C)。

これは本当に良いですか?多分、そして多分そうではありません。

しかし、いずれにせよ、あなたはすでに1つの重要なポイントを理解しています。巧妙な最適化には広範なテストが必要です。上記は正しいと思いますが、これがもっと速くなるかどうかさえわかりません。結局のところ、 1つはfor 、もう1father_of/2つはforの代わりに、のルックアップが2つあります。ナイーブバージョンはすぐに速くなるかもしれません...father_of/2mother_of/2

于 2012-11-16T00:08:18.273 に答える
0

この目的のために、一部の Prolog システムでは「ソフト カット」が提供されています*->/2

parent_of(X,Y) :- father_of(X,Y) *-> true ; mother_of(X,Y).

一般にIf *-> Then ; Else、条件Ifが成功した場合、 for が実行され、 on バックトラッキングでとThenの代替ソリューションのみが返されます。がまったく解決しない場合にのみ実行されます。IfThenIfElse

これには、述語のモード、つまり呼び出しパターンを知っている必要があります。あなたのケースでは、述語のモードが である場合、parent_ofソフトparent_of(++,?)カットを追加しても問題ありません (名前が一意であるか、1 つの性別にのみ表示されると仮定します)。の場合parent_of(++,++)、通常のカットでも問題ありませんが、データベースに重複するファクトがない限り不要です (対称性の破れはカットの使用例の 1 つです)。ただし、 にも対応する必要がある場合parent_of(-,?)、カットは本当にソリューションをカットします。

一般的に: 切り取った検索ツリーのブランチに解が含まれていないか、関心のない対称解のみが含まれていることが確実な場合にのみ、カットを使用してください。

于 2012-11-16T07:16:02.480 に答える