问题
I'm working on solving a logic puzzle using prolog for school. Here's the clues:
Brown, Clark, Jones and Smith are 4 substantial citizens who serve their community as achitect, banker, doctor and lawyer, though not necessarily respectively.
Brown, who is more conservative 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.
The banker, who earns more than the architect, is neither the youngest nor the oldest.
The doctor, who is a poorer golfer than the lawyer, is less conservative than the architect.
As might be expected, the oldest man is the most conservative and has the largest income, and the youngest man is the best golfer.
What is each man's profession?
hint: to rank people for weath, ability, relative age, etc use the numbers 1,2,3,4 Be careful to state whether 1 represents, e.g., youngest or oldest. Doing this makes comparisons easy to code.
To code (as follows) interprets all the relationships, given by the clues, as a list of lists, wherein each list defines the
%[profession,surname,politics,relative_age, relative_salary, golf_ability]:
profession(L) :- L = [[_,'Brown',_,_,_,_],[_,'Jones',_,_,_,_],[_,'Clark',_,_,_,_],
[_,'Smith',_,_,_,_]],
member([_,'Brown',P1,A6,M3,G3],L),
member([_,'Jones',P2,_,_,_],L),
member([_,'Clark',_,A3,_,_],L),
member([_,'Smith',P3,_,_,_],L),
moreconservative(P1,P2),
moreliberal(P1,P3),
bettergolfer(G3,younger(_,A6)),
richer(M3,older(_,A3)),
member(['banker',_,_,A1,M1,_],L),
member(['architect',_,P5,_,M2,_],L),
richer(M1,M2),
(A1 = 2;A1 = 3),
member(['doctor',_,P4,_,_,G1],L),
member(['lawyer',_,_,_,_,G2],L),
worsegolfer(G1,G2),
moreliberal(P4,P5),
member([_,_,4,4,4,_],L),
member([_,_,_,1,_,4],L).
I define the relative_politics,relative_salary,relative_age, and golf_ability relationships like so
EG:
richer(4,1).
moreconservative(4,1).
poorer(1,4).
poorer(1,3).
And it goes on for all relationships.
I think I have faithfully translated all of the clues to prolog but it just says fail when I query the database. EG:
?- profession(L).
fail.
I am using NU Prolog. I'm wondering if I made an error in my translation of the clues or I omitted a fact that is needed for the database to satisfy all the conditions of the list L.
回答1:
bettergolfer(G3,younger(_,A6))
... it doesn't work this way, in Prolog. Instead, have this
( member( X,L), age(X,AX), golf(X,GX),
( younger(AX,A6) -> better_golfer(G3,GX) ; true )),
.....
age( [_,_,_,A,_,_],A).
golf([_,_,_,_,_,G],G).
.....
this means, all the persons (including none) that are younger than Brown, must be poorer golfers than he is.
There is a catch here, too. Since we're told about the men younger than Brown, it means there must exist at least one such man (unlike in the mathematical definition of implication). We have to code this too. For example,
( member(X,L), age(X,AX), younger(AX,A6) -> true ),
.....
(using unique names for the new logvars of course). You'll have to make the same transformation for your richer(M3,older(_,A3))
.
Great idea BTW, to have the comparison predicates defined in a generative fashion:
poorer(1,2).
poorer(1,3).
poorer(1,4).
poorer(2,3).
poorer(2,4).
poorer(3,4).
richer(A,B):- poorer(B,A)
If you were to define them as arithmetic comparisons, poorer(A,B):- A<B.
, you could potentially run into problems with uninstantiated variables (as recently discussed here).
来源:https://stackoverflow.com/questions/20079467/solving-caliban-problems-with-prolog