我帖子末尾的代码应该回答以下难题:
布朗,克拉克,琼斯和史密斯是4名服务的重要公民 他们的社区是建筑师,银行家,医生和律师,但不是 必然分别。布朗,比琼斯更保守 但比史密斯更自由,是一个比男人更好的高尔夫球手 年轻人比他年轻,收入高于老年人 比克拉克。这位银行家的收入高于建筑师,但他不是 最小的也不是最老的。
比律师更差的高尔夫球手的医生更少 比建筑师保守。正如所料,最年长的人 是最保守的,收入最多,也是最年轻的 男人是最好的高尔夫球手。每个男人的职业是什么?
代码:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% We represent each "person" with a six-tuple of the form
%
% [ name , profession , age , income , politics , golf ranking ]
%
% where name is either brown, clark, jones, or smith
% profession is either banker, lawyer, doctor, or architect
% age is a range 1 .. 4, with 1 being the youngest and 4 the oldest
% income is a range 1 .. 4, with 1 being the least and 4 the most
% politics is a range 1 .. 4, with 1 being conservative, 4 liberal
% golf ranking is a range 1 .. 4, 1 for the best rank, 4 for the worst
%
:- use_module(library(clpfd)).
solutions(L) :- L = [ [brown, _, _, _, _, _], [clark, _, _, _, _, _],
[jones, _, _, _, _, _], [smith, _, _, _, _, _] ],
clue1(L),
clue2(L),
clue3(L),
clue4(L),
constrained_profession(L),
constrained_age(L),
constrained_income(L),
constrained_politics(L),
constrained_golf_rank(L).
%
% clue #1
% brown, who is more conservateive than jones but
% more liberal than smith, is a better golfer than
% the men who are younger than he is and has a larger
% income than the men who are older than clark
%
clue1(L) :- member(P1,L), member(P2,L), member(P3,L),
P1 = [brown, _, A1, _, L1, G1],
P2 = [jones, _, _, _, L2, _],
P3 = [smith, _, _, _, L3, _],
liberaler( P2, P1 ),
liberaler( P1, P3 ),
not( clue1_helper_a(L) ),
not( clue1_helper_b(L) ).
% for all men younger than brown he is a better golfer ===>
% it is not the case that there exists a man younger than brown
% such that brown is not a better golfer than him.
% The "is not the case" is taken care of in clue1.
clue1_helper_a(L) :- member(P1,L), P1 = [brown, _, A1, _, L1, G1],
member(PU,L), PU = [_, _, AU, _, _, GU],
younger(PU,P1),
not(golfier(P1, PU)).
% for all men older than clark, brown makes more money than they do ===>
% it is not the case that there exists a man older than clark such that
% brown does not make more money than him.
% The "is not the case" is taken care of in clue1.
clue1_helper_b(L) :- member(P1,L), P1 = [brown, _, _, _, _, _],
member(P2,L), P2 = [clark, _, _, _, _, _],
member(PU,L), PU = [_, _, _, _, _, _],
younger(P2,PU),
not(richer(P1, PU)).
%
% clue #2
% the banker, who earns more than the archiect, is
% neither the youngest nor the oldest
%
clue2(L) :- member(P1,L), member(P2,L),
P1 = [_, banker, A1, I1, _, _],
P2 = [_, architect, _, I2, _, _],
richer(P1,P2),
not( A1 = 1 ),
not( A1 = 4 ).
%
% clue #3
% the doctor, who is a pooer golfer than the lawyer, is
% less conservative than the architect.
%
clue3(L) :- member(P1, L), member(P2, L), member(P3,L),
P1 = [_,doctor, _, _, L1, G1],
P2 = [_,lawyer, _, _, _, G2],
P3 = [_,architect, _, _, L3, _],
golfier(P2,P1),
liberaler(P1,P3).
%
% clue #4
% as might be expected, the oldest man is the most
% conservative and has the largest income, and the
% youngest man is the best golfer.
clue4(L) :- member(P1,L), member(P2,L),
P1 = [_, _, 4, 4, 1, _],
P2 = [_, _, 1, _, _, 1].
%
% relations
%
younger(X,Y) :- X = [_, _, AX, _, _, _], Y = [_, _, AY, _, _, _], AX #< AY.
liberaler(X,Y) :- X = [_, _, _, _, LX, _], Y = [_, _, _, _, LY, _], LX #> LY.
golfier(X,Y) :- X = [_, _, _, _, _, GX], Y = [_, _, _, _, _, GY], GX #< GY.
richer(X,Y) :- X = [_, _, _, IX, _, _], Y = [_, _, _, IY, _, _], IX #> IY.
%
% constraints
%
constrained_profession(L) :-
member(P1,L), member(P2,L), member(P3,L), member(P4,L),
P1 = [_, banker, _, _, _, _],
P2 = [_, lawyer, _, _, _, _],
P3 = [_, doctor, _, _, _, _],
P4 = [_, architect, _, _, _, _].
constrained_age(L) :-
member(P1,L), member(P2,L), member(P3,L), member(P4,L),
P1 = [_, _, 1, _, _, _],
P2 = [_, _, 2, _, _, _],
P3 = [_, _, 3, _, _, _],
P4 = [_, _, 4, _, _, _].
constrained_income(L) :-
member(P1,L), member(P2,L), member(P3,L), member(P4,L),
P1 = [_, _, _, 1, _, _],
P2 = [_, _, _, 2, _, _],
P3 = [_, _, _, 3, _, _],
P4 = [_, _, _, 4, _, _].
constrained_politics(L) :-
member(P1,L), member(P2,L), member(P3,L), member(P4,L),
P1 = [_, _, _, _, 1, _],
P2 = [_, _, _, _, 2, _],
P3 = [_, _, _, _, 3, _],
P4 = [_, _, _, _, 4, _].
constrained_golf_rank(L) :-
member(P1,L), member(P2,L), member(P3,L), member(P4,L),
P1 = [_, _, _, _, _, 1],
P2 = [_, _, _, _, _, 2],
P3 = [_, _, _, _, _, 3],
P4 = [_, _, _, _, _, 4].
% end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
然而,当我运行它时,它返回false!
?- solutions(L).
false.
有人可以帮我吗?
答案 0 :(得分:3)
我不会为您解决整个问题,但我想解释一下让您快速缩小此类问题的一般方法。
总结一下,我们有以下主谓词:
solutions(L) :- L = [ [brown, _, _, _, _, _], [clark, _, _, _, _, _], [jones, _, _, _, _, _], [smith, _, _, _, _, _] ], clue1(L), clue2(L), clue3(L), clue4(L), constrained_profession(L), constrained_age(L), constrained_income(L), constrained_politics(L), constrained_golf_rank(L).
意外失败即使对于最常见的查询,其中所有参数都是新变量:
?- solutions(L). false.
为什么失败了?与 GUPU 一样,我将使用program-slicing,使用以下定义来概括目标:
:- op(920, fy, *). *_.
如果您在计划中加入此内容,则可以在目标前使用(*)/1
来“删除”。这可以使得到的程序最多更通用。
例如,让我们现在概括所有目标(我使用删除文本来表明目标不再限制解决方案,因为它被推广掉了):
solutions(L) :- *L = [ [brown, _, _, _, _, _], [clark, _, _, _, _, _], [jones, _, _, _, _, _], [smith, _, _, _, _, _] ],*clue1(L),*clue2(L),*clue3(L),*clue4(L),*constrained_profession(L),*constrained_age(L),*constrained_income(L),*constrained_politics(L),*constrained_golf_rank(L).
现在查询成功:
?- solutions(L). true.
然而,该计划现在显然过于笼统。现在重点:我们可以有选择地重新引入目标(= 约束)来定位导致程序意外失败的错误。
例如,我选择第一个目标和clue2/1
目标,然后移除前面的(*)/1
:
solutions(L) :- L = [ [brown, _, _, _, _, _], [clark, _, _, _, _, _], [jones, _, _, _, _, _], [smith, _, _, _, _, _] ], *clue1(L),clue2(L), *clue3(L),*clue4(L),*constrained_profession(L),*constrained_age(L),*constrained_income(L),*constrained_politics(L),*constrained_golf_rank(L).
现在,我们再次:
?- solutions(L). false.
据此,您知道clue2/1
必须包含错误。这是因为任何进一步的目标都可以使谓词最多更具体,并且它们无法消除此目标的失败。
让我们重新考虑clue2/1
:
clue2(L) :- member(P1,L), member(P2,L), P1 = [_, banker, A1, I1, _, _], P2 = [_, architect, _, I2, _, _], richer(P1,P2), not( A1 = 1 ), not( A1 = 4 ).
这里的错误在于使用非单调谓词not/1
,在这种情况下,错误会删除解决方案。检查一下,即使是非常一般的查询,我们也没有得到这个谓词的答案:
?- length(Ls, 4), clue2(Ls). false.
怎么办?回答:
而不是
not/1
或(\+)/1
,使用约束来表达不平等。
约束是真正的关系,可以在所有方向上使用,即使它的一些或所有参数都是自由变量!
在您的情况下,使用dif/2
或更好的 CLP(FD)约束 (#\=)/2
来表示两个整数不同< / EM>:
clue2(L) :- member(P1,L), member(P2,L), P1 = [_, banker, A1, I1, _, _], P2 = [_, architect, _, I2, _, _], richer(P1,P2), A1 #\= 1, A1 #\= 4.
通过这个简单的更改,谓词现在可以产生答案,而缩小程序成功可用于最常见的查询。
通过系统地应用此声明性调试技术,您可以纠正其他谓词中的剩余错误。我将此作为练习。