1

論理的な問題があります。イヴァン、ペトル、ミハイル、セルゲイの 4 人の友人は、さまざまな方法で時間を過ごしました。2 人はチェスをし、1 人は本を読み、1 人はテレビを見ました。セルゲイがチェスをせず、ペトルがテレビを見なかった場合、誰が何をするかを見つけてください。

これが私の解決策です:

PREDICATES
    question(string,string,string,string)
    friend(string)
    readBook(string)
    watchTV(string)
    playsChess(string, string)

CLAUSES
    friend(ivan).
    friend(petr).
    friend(mikhail).
    friend(sergey).

    readBook(X):-
        friend(X).

    watchTV(X):-
        friend(X),
        X<>"petr".

    playsChess(X,Y):-
        friend(X),
        friend(Y),
        X<>Y,
        X<>"sergey",
        Y<>"sergey".

    question(A,B,C,D):-
        friend(A),
        friend(B),
        friend(C),
        friend(D),
        playsChess(A,B),
        readBook(C),
        watchTV(D),
        A<>B, A<>C, A<>D,
        B<>C, B<>D,
        C<>D.
GOAL
    question(A,B,C,D).

私は次の解決策を持っています:

A=ivan, B=petr, C=mikhail, D=sergey (1)
A=ivan, B=petr, C=sergey, D=mikhail (2)
A=ivan, B=mikhail, C=petr, D=sergey (3)
A=petr, B=ivan, C=mikhail, D=sergey (4)
A=petr, B=ivan, C=sergey, D=mikhail (5)
A=petr, B=mikhail, C=ivan, D=sergey (6)
A=petr, B=mikhail, C=sergey, D=ivan (7)
A=mikhail, B=ivan, C=petr, D=sergey (8)
A=mikhail, B=petr, C=ivan, D=sergey (9)
A=mikhail, B=petr, C=sergey, D=ivan (10)
10 Solutions

ただし、A と B が結合されているため、冗長な行もあります。ここで使用しようとし!ました:

playsChess(X,Y):-!,
    friend(X),
    friend(Y),
    X<>Y,
    X<>"sergey",
    Y<>"sergey".

しかし、それは効果がありません。問題は、どうすれば過剰な解の結果を取り除くことができるかということです。

4

2 に答える 2

3

友達ごとに紹介する変数を使用して、その人に対応するアクティビティを直接表すことを検討してください。

friends([ivan=Ivan,petr=Petr,mikhail=Mikhail,sergey=Sergey]) :-
        Fs0 = [Ivan,Petr,Mikhail,Sergey],
        dif(Sergey, chess),
        dif(Petr, tv),
        select(books, Fs0, Fs1),
        select(tv, Fs1, [chess,chess]).

クエリとその結果の例:

?- friends(Fs).
Fs = [ivan=books, petr=chess, mikhail=chess, sergey=tv] ;
Fs = [ivan=chess, petr=books, mikhail=chess, sergey=tv] ;
Fs = [ivan=chess, petr=chess, mikhail=books, sergey=tv] ;
Fs = [ivan=tv, petr=chess, mikhail=chess, sergey=books] ;
Fs = [ivan=chess, petr=chess, mikhail=tv, sergey=books] ;
false.
于 2015-02-25T20:20:23.073 に答える
2

問題を解決する最も簡単な方法は、一方を他方よりも「大きく」するように制約Aし、さらに強制することです。Bこれが Visual Prolog の構文であるかどうか正確にはわかりませんが、これを試してください。A > Bの代わりに を使用していることに注意してくださいA <> B

question(A,B,C,D):-
    friend(A),
    friend(B),
    friend(C),
    friend(D),
    playsChess(A,B),
    readBook(C),
    watchTV(D),
    A > B, A<>C, A<>D,
    B<>C, B<>D,
    C<>D.

>あなたの代わりに制約する<>ことで、対称的なケースがなくなることが保証されます。たとえば、a > bは偽ですが、a < b真です。ただし、 と の両方a <> bb <> a真なので、は と の両方を<>与えます。a, bb, a

あなたの cut ( !) は、次のような句が 1 つしかない述語で使用すると、何もしませんでした。

my_predicate(...) :- !, subqueries ...

最初のサブクエリの先頭を超えてバックトラックしないように Prolog に指示するだけです。my_predicateとにかくバックトラックする他の句がないため、効果はありません。

于 2015-02-25T20:20:15.117 に答える