Prolog逻辑任务
Prolog logical task
逻辑有问题:
四个朋友:Ivan、Petr、Mikhail、Sergey 以不同的方式度过他们的时间:两个下棋,一个看书,一个看电视。找出如果 Sergey 不下国际象棋而 Petr 不看电视谁会做什么。
这是我的解决方案:
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 的组合。例如第 (1) 和 (4) 行(A=ivan,B=petr 和 A=petr,B=ivan)。
我在这里尝试使用 !
:
playsChess(X,Y):-!,
friend(X),
friend(Y),
X<>Y,
X<>"sergey",
Y<>"sergey".
但是没有效果。
所以问题是:我怎样才能摆脱多余的解决方案结果?
解决该问题的最简单方法是进一步限制 A
和 B
,并强制其中一个比另一个 "greater"。我不确定这是否是 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 <> b
和 b <> a
都为真,因此 <>
给出 a, b
和 b, a
。
您的剪辑 (!
) 没有任何作用,因为当您在只有一个子句的谓词上使用它时:
my_predicate(...) :- !, subqueries ...
它只是告诉 Prolog 不要回溯到第一个子查询的开头之外。由于无论如何都没有其他 my_predicate
子句可以回溯,因此它没有任何效果。
考虑用你为每个朋友介绍的变量直接代表那个人对应的activity:
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.
逻辑有问题: 四个朋友:Ivan、Petr、Mikhail、Sergey 以不同的方式度过他们的时间:两个下棋,一个看书,一个看电视。找出如果 Sergey 不下国际象棋而 Petr 不看电视谁会做什么。
这是我的解决方案:
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 的组合。例如第 (1) 和 (4) 行(A=ivan,B=petr 和 A=petr,B=ivan)。
我在这里尝试使用 !
:
playsChess(X,Y):-!,
friend(X),
friend(Y),
X<>Y,
X<>"sergey",
Y<>"sergey".
但是没有效果。 所以问题是:我怎样才能摆脱多余的解决方案结果?
解决该问题的最简单方法是进一步限制 A
和 B
,并强制其中一个比另一个 "greater"。我不确定这是否是 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 <> b
和 b <> a
都为真,因此 <>
给出 a, b
和 b, a
。
您的剪辑 (!
) 没有任何作用,因为当您在只有一个子句的谓词上使用它时:
my_predicate(...) :- !, subqueries ...
它只是告诉 Prolog 不要回溯到第一个子查询的开头之外。由于无论如何都没有其他 my_predicate
子句可以回溯,因此它没有任何效果。
考虑用你为每个朋友介绍的变量直接代表那个人对应的activity:
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.