3

私には次の事実とルールがあります。

% frequents(D,P) % D=drinker, P=pub
% serves(P,B) % B=beer
% likes(D,B)

frequents(janus, godthaab).
frequents(janus, goldenekrone).
frequents(yanai, goldenekrone).
frequents(dimi,  schlosskeller).

serves(godthaab, tuborg).
serves(godthaab, carlsberg).
serves(goldenekrone, pfungstaedter).
serves(schlosskeller, fix).

likes(janus, tuborg).
likes(janus, carlsberg).

count_good_beers_for_at(D,P,F) :- group_by((frequents(D,P), serves(P,B), likes(D,B)),[D,P],(F = count)).
possible_beers_served_for_at(D,P,B) :- lj(serves(P,B), frequents(D,R), P=R).

ここで、「飲酒者」「頻繁」が0より大きい各パブで利用可能な「いいね」ビールの数が「真」を返す述語のように機能するルールを作成したいと思います。

ルールがタプルを返さない場合、述語はtrueと見なされます。述語が偽の場合、「いいね」したビールが1つもないバーを返すように計画していました。

ご覧のとおり、私はすでに、特定のパブで特定の酒飲みに適したビールを数えるルールを持っています。また、提供できるビールの数を指定するルールもあります。

DES> count_good_beers_for_at(A,B,C)

{                                           
  count_good_beers_for_at(janus,godthaab,2)
}
Info: 1 tuple computed.          

ご覧のとおり、カウンターには頻繁に訪れたパブは返されませんが、好きなビールは0本あります。左外側の結合を使用してこれを回避することを計画していました。

DES> is_happy_at(D,P,Z) :- lj(serves(P,B), count_good_beers_for_at(D,Y,Z), (Y=P))

Info: Processing:
  is_happy_at(D,P,Z) :-
    lj(serves(P,B),count_good_beers_for_at(D,Y,Z),Y = P).
{                                           
  is_happy_at(janus,godthaab,2),
  is_happy_at(null,goldenekrone,null),
  is_happy_at(null,schlosskeller,null)
}
Info: 3 tuples computed.

これはほとんど正しいですが、それは私に頻繁ではないパブも与えていることを除いて。条件を追加してみます:

DES> is_happy_at(D,P,Z) :- lj(serves(P,B), count_good_beers_for_at(D,Y,Z), (Y=P)), frequents(D,P)

Info: Processing:
  is_happy_at(D,P,Z) :-
    lj(serves(P,B),count_good_beers_for_at(D,Y,Z),Y = P),
    frequents(D,P).
{                                           
  is_happy_at(janus,godthaab,2)
}
Info: 1 tuple computed.

今、私はどういうわけかnullを含むすべてをフィルターで除去しました!これはDESのnull値ロジックが原因だと思います。

私はこの問題全体に間違った方法で取り組んでいる可能性があることを認識しています。どんな助けでも大歓迎です。

編集:割り当ては「very_happy(D)ist wahr、gena​​u dann wenn jede Bar、die Trinker D besucht、wenigstens ein Bier ausschenkt、dasermag」です。これは、「very_happy(D)が真であり、各バーを飲む人Dが訪れた場合、彼が好きなビールを少なくとも1杯提供する」という意味になります。この課題はDatalogに関するものなので、Prologを使わなくても間違いなく解決できると思います。

4

2 に答える 2

4

割り当てには、集計を悪用することなく、基本的な Datalog を使用する必要があると思います。問題のポイントは、普遍的に定量化された条件をどのように表現するかです。「普遍的な定量化データログ」をグーグルで検索したところ、最初の位置で次のことを主張するdeductnotes.pdfが見つかりました。

全称量化された条件は、存在量化と否定を伴う同等の条件によってのみ表現できます。

その PDF には、役立つ例も含まれています (pagg 9 & 10)。

したがって、質問を言い換える必要があります。私はこのコードで終わった:

not_happy(D) :-
  frequents(D, P),
  likes(D, B),
  not(serves(P, B)).

very_happy(D) :-
  likes(D, _),
  not(not_happy(D)).

それが必要なようです:

DES> very_happy(D)

{                                           
}
Info: 0 tuple computed.          

likes(D, _)yanai と dimi が、好きなものを明示的に主張せずに、very_happy としてリストされることを避けるために必要であることに注意してください(OT 申し訳ありませんが、私の英語は本当に下手です...)

編集:申し訳ありませんが、上記の解決策は機能しません。私はこのように書き直しました:

likes_pub(D, P) :-
  likes(D, B),
  serves(P, B).

unhappy(D) :-
  frequents(D, P),
  not(likes_pub(D, P)).

very_happy(D) :-
  likes(D, _),
  not(unhappy(D)).

テスト:

DES> unhappy(D)

{                                           
  unhappy(dimi),
  unhappy(janus),
  unhappy(yanai)
}
Info: 3 tuples computed.          

DES> very_happy(D)

{                                           
}
Info: 0 tuples computed.          

次にファクトを追加します。

serves(goldenekrone, tuborg).

修正されたコードの結果を確認できます。

DES> unhappy(D)

{                                           
  unhappy(dimi),
  unhappy(yanai)
}
Info: 2 tuples computed.          

DES> very_happy(D)

{                                           
  very_happy(janus)
}
Info: 1 tuple computed.          
于 2012-06-07T19:17:16.420 に答える
2

あなたが期待している答えではないかもしれません。ただし、通常の Prolog を使用して、bagof/3 または setof/3 の組み込み述語を使用してグループ化クエリを簡単に実行できます。

?- bagof(B,(frequents(D,P), serves(P,B), likes(D,B)),L), length(L,N).
D = janus,
P = godthaab,
L = [tuborg,carlsberg],
N = 2

bagof/3 のセマンティクスは、指定されたクエリの外部結合を計算しないようになっています。クエリは通常、Prolog によって実行されます。結果は最初に蓄積され、キーがソートされます。最後に、バックトラックによって結果が返されます。データログが null なしでは実行できない場合は、はい、フィルタリングする必要があります。

ただし、好きなビールの存在だけを知りたい場合は、集計に入る必要はありません。集計なしでクエリを介して直接実行できます。

is_happy_at(D,P) :- frequents(D,P), once((serves(P,B), likes(D,B))).
?- is_happy_at(D,P).
D = janus,
P = godthaab ;
Nein

once/1 は不要なバックトラックを防ぎます。Datalog は、is_happy_at/2 で射影が見られる場合、つまり B が離れて射影されると、不要なバックトラッキングを自動的に行わない場合があります。または、SQL DISTINCT に対応するものを明示的に使用する必要がある場合があります。または、最終的に、データログは、once/1 に最もよく対応する SQL EXISTS に対応するものを提供します。

さよなら

于 2012-06-07T09:20:37.977 に答える