論理を整理することは、一貫性の問題であり、特定の述語または事実の矛盾する意味を回避することです。
の定義sad/1
は現在、クエリへのバックトラックごとに 1 つの結果が得られるという事実ですsad(X)
。しかし、あなたの定義はhappy/1
リストを生成します。これにより、リストを生成するためにどのように定義したいかが残ります。これは、引数が悲しい人である場合に真であるクエリとしてのsad/1
現在の定義と競合します。sad/1
より一貫したアプローチは、 がhappy/1
動作するように動作するように定義することsad/1
です。
happy(X) :-
person(X),
\+ sad(X).
次に、リストのバージョンを定義できます。
happy_all(A) :-
findall(X, happy(X), A).
sad_all(A) :-
findall(X, sad(X), A).
person/1
上記は、すべての有効な人々の宇宙sad/1
を定義し、悲しい人が誰であるかを定義する明確な事実があることを前提としています。また、人が悲しんでいない場合、幸せに違いないと仮定しています。
これをひっくり返して、幸せな人をhappy/1
事実で明示的に定義し、幸せsad/1
でない人を定義して、悲しいことがなければ幸せに違いないと仮定することができます。
sad(X) :-
person(X),
\+ sad(X).
and述語は引き続き適用されますhappy_all/1
。sad_all/1
happy/1
事実をと と混ぜ合わせたい場合sad/1
、これは一貫性の問題を引き起こす可能性があります: (1) 人が幸せまたは悲しいと定義されていない場合... では、彼らは何ですか? (2) 人が幸せで悲しいと定義されている場合はどうなりますか?
意味的には、誰かが幸せでも悲しんでもいないことを許可する場合sad/1
は、 と の両方をhappy/1
明示的に定義することをお勧めします。あなたはこれを行うことができます:
person(bob).
person(tim).
person(steve).
person(roy).
person(jack).
sad(bob).
sad(tim).
happy(steve).
happy(roy).
happy_all(A) :-
findall(X, happy(X), A).
sad_all(A) :-
findall(X, sad(X), A).
ただし、述語は既に事実であるため、述語を定義しないでください。それは物事をシンプルに保ちます。幸せなのか悲しいのかわかりません。happy/1
sad/1
jack
しかし、人が幸せでも悲しくもない場合は、幸せで、そのルールを元に戻す必要があると言いたい場合はどうでしょう。あなたが言及したループを避けるために、ルール名とファクト名を混在させません。その場合:
person(bob).
person(tim).
person(steve).
person(roy).
person(jack).
sad(bob).
sad(tim).
happy(steve).
happy(roy).
% A person is happy if they are, in fact, happy
happy_person(X) :-
happy(X),
% A person is happy if they are neither happy or sad
happy_person(X) :-
person(X),
\+ happy(X),
\+ sad(X).
% A person is sad if they are, in fact, sad
sad_person(X) :-
sad(X).
% Who are all the happy people?
happy_all(A) :-
findall(X, happy_person(X), A).
% Who are all the sad people?
sad_all(A) :-
findall(X, sad_person(X), A).