0

事実について「一般的に」どのように述べればよいでしょうか? 「誰もが彼/彼女を好きな人を好きだ」と述べる必要があり、お互いに好きかもしれないし嫌いかもしれない人々のリストがあるとします。

これは私がこれまでに試したことですが、それを行う方法ではないことは確かです:

likes(dana, cody).
hates(bess, dana).
hates(cody, abby).

likes(first(Girl, OtherGirl), first(OtherGirl, Girl)).
hates(Girl, OtherGirl):- \+ likes(Girl, OtherGirl).

これはコンパイルすらできないからです。


everybody([dana, cody, bess, abby]).

likes_reflexive(dana, cody).
hates(bess, dana).
hates(cody, abby).
likes_reflexive(X, Y):- likes(X, Y), likes(Y, X).

hates(Girl, OtherGirl):- \+ likes(Girl, OtherGirl).

%% likes_reflikes_reflexive(X, Y):- likes(X, Y), likes(Y, X).
%% user:6: warning: discontiguous predicate likes_reflexive/2 - clause ignored

%% hates(Girhates(Girl, OtherGirl):- \+ likes(Girl, OtherGirl).
%% user:8: warning: discontiguous predicate hates/2 - clause ignored

残念ながら、警告の意味がわかりません。私の意図がより明確になることを願っています。つまり、1 つの事実を述べることで、関連するもう 1 つの事実も述べたいと思います。

4

3 に答える 3

1

assertナレッジ ベースを動的に変更する場合は、 sを使用できます。既存の述語を変更する場合は、次のように定義する必要がありdynamicます:- dynamic(likes/2).。predicate が定義されていない場合は省略できます。

add_mutual_likes(X, Y) :- asserta(likes(X, Y)), asserta(likes(Y, X)).

:- initialization(add_mutual_likes(dana, cody)).

initialization/1add_mutual_likes(data, cody)ファイルがロードされたときにゴールを 呼び出します。add_mutual_likes/2データベースに 2 つのファクトを追加します。asserta/1その引数を句に変換し、データベースに追加します。

| ?- [my].
yes
| ?- listing(likes/2).
% file: user_input

likes(cody, dana).
likes(dana, cody).

yes
| ?- likes(cody, dana).
yes
| ?- likes(dana, cody).
yes

| ?- add_mutual_likes(oleg, semen).
yes
| ?- listing(likes/2).
% file: user_input

likes(semen, oleg).
likes(oleg, semen).
likes(cody, data).
likes(data, cody).

yes

私は使用しますgprolog

于 2013-10-01T07:15:10.657 に答える
0

警告から始めましょう。それらは単なる「スタイル」の提案です。彼らは、好き嫌いの定義はすべて一緒にすべきだと言っています。大規模な Prolog プログラムを使用している場合、述語の完全な定義を取得するためにツアー コードを調べるのは悪夢になります。関数の半分を C++ で記述して、別のファイルで終了するようなものです。

ここで、「好きな人はみんな好き」と言いたいですよね。コードでその関数を「最初に」使用している理由がわかりません。これで十分です:

likes(dana, cody).
likes(Girl, OtherGirl) :- likes(OtherGirl, Girl).

2 番目の句は、「OtherGirl が Girl が好きな場合、Girl は OtherGirl が好きです。これは機能しません。プログラムに「cody が dana が好きなのは本当ですか」と尋ねると、

? likes(cody, dana)

Prolog は次のように推論します。

  • dana が cody を好む場合、答えは yes です (2 番目の節を使用)。
  • はい!dana は cody が好きなので (最初の節を使用)。

これは正しいプログラムにするのに十分ではありません。私たちは Prolog にいるので、"give me another solution" と言うことができます (通常はプロンプトに ";" を入力します)。Prolog は、「最初の句だけを使用し、2 番目の句は試していない」と考えます。

  • dana が cody が好きな場合も (2 番目の句を使用して)、答えは Yes です。
  • cody が dana を気に入っている場合、2 番目の節によると、答えは Yes です。

しかし、それは私たちの最初の質問です。Prolog は何度も何度も同じ答えを返し、すべての解を求めると永遠にループします。

ここでできることは 2 つあります。1 つ目は、1 つのソリューションで十分であることを Prolog に伝えることです。これを行うには、「!」を追加します。(基本的には、開いているブランチをすべてクリアして探索する必要があります)。

likes(dana, cody) :- !.
likes(Girl, OtherGirl) :- likes(OtherGirl, Girl).

別の選択肢は、「プログラムを階層化する」ことです。

direct_likes(dana, cody).
likes(Girl, OtherGirl) :- direct_likes(OtherGirl, Girl), !.
likes(Girl, OtherGirl) :- direct_likes(Girl, OtherGirl).
于 2013-10-01T12:21:20.850 に答える
0

あなたが望むのは、Prolog が引数の順序を気にしないという事実です。残念ながら、そのようなものは存在しません。代わりにできることは、暗黙の意味がすべての引数順序に対して有効であるという事実を定義することです (like_each以下の例)。しかしもちろん、これらの事実をそのように使用することはできません。代わりに、実際の述語を定義して、;考えられるすべての引数の順序を試行します (したがって、 or )。

したがって、解決策は次のとおりです。

%% bi-directional like
like_each(dana, cody).

likes(A, B) :- like_each(A, B); like_each(B, A).

%% optional: one-directional like
% likes(cody, sarah).

また、注意してください

hates(Girl, OtherGirl):- \+ likes(Girl, OtherGirl).

両方の変数がバインドされていない場合 (例: ?- hates(A,B))、常に失敗します。これは、Prolog が最初に の一致を見つけようとしlikes、2 つの変数に対して常に成功し、結果を否定するために発生します。したがって、 を使用hatesして互いに嫌いなすべてのペアを見つけることはできません。

于 2013-10-01T07:34:56.963 に答える