The problem is
Brown, Clark, Jones and Smith are four substantial citizens who serve the community as architect, banker, doctor and lawyer, though not necessarily respe
You code works exactly as expected if you just use finite domain constraints instead of lower-level arithmetic. For example, use (#>)/2
instead of (>)/2
.
After you get it to run beyond this instantiation error by using constraints, you will then notice that among other things, your code has a typo: banker_
. Also, you are not formulating the implication correctly, and your predicate will therefore yield false
.
Here is a slightly modified version of your code, changed to use finite domain constraints and correcting the two mentioned mistakes:
:- use_module(library(clpfd)).
older_worse_golfer([], _, _).
older_worse_golfer([[_,_,_,G,_,A]|Rest], G0, A0) :-
A #> A0 #==> G #< G0,
older_worse_golfer(Rest, G0, A0).
younger_higher_income([], _, _).
younger_higher_income([[_,_,_,_,I,A]|Rest], I0, A0) :-
A #< A0 #==> I0 #> I,
younger_higher_income(Rest, I0, A0).
man_profession_rest([M,P|Rest], M-P, Rest).
jobs(Ls, Vs) :-
Ls = [[brown,_,_,_,_,_],
[clark,_,_,_,_,_],
[jones,_,_,_,_,_],
[smith,_,_,_,_,_]],
maplist(man_profession_rest, Ls, _, Rests),
append(Rests, Vs),
Vs ins 1..4,
% [name,job,conservative,golf,income,age]
% conserative: 1 = least conservative, 4 = most conservative
% golf: 1 = worst golfer, 4 = best golfer
% income: 1 = least income, 4 = highest income
% age: 1 = youngest, 4 = oldest
% Oldest is most conservative and has highest income.
member([_,_,4,_,4,4], Ls),
% Brown is more conservative than Jones. Brown is less
% conservative than Smith.
memberchk([brown,_,C1,_,_,_], Ls),
memberchk([jones,_,C2,_,_,_], Ls),
memberchk([smith,_,C3,_,_,_], Ls),
C1 #> C2,
C1 #< C3,
% Brown is a better golfer than those older than him.
memberchk([brown,_,_,G1,_,A1], Ls),
older_worse_golfer(Ls, G1, A1),
% IMPLIED: Brown is not the oldest
A1 #< 4,
% Brown has a higher income than those younger than Clark.
memberchk([brown,_,_,_,I1,_], Ls),
memberchk([clark,_,_,_,_,A3], Ls),
younger_higher_income(Ls, I1, A3),
% IMPLIED: Clark is not the youngest
A3 #> 1,
% Banker has a higher income than architect. Banker is neither
% youngest nor oldest.
I3 #> I4,
A5 in 2..3,
member([_,banker,_,_,I3,A5], Ls),
member([_,architect,_,_,I4,_], Ls),
% Doctor is a worse golfer than lawyer. Doctor is less
% conservative than architect.
member([_,doctor,C4,G3,_,_], Ls),
member([_,lawyer,_,G4,_,_], Ls),
member([_,architect,C5,_,_,_], Ls),
G3 #< G4,
C4 #< C5,
% Youngest is the best golfer.
member([_,_,_,4,_,1], Ls).
You can use label/1
to search for concrete solutions. As you can see with the following query, there is a unique solution with respect to professions:
?- time(setof(MP, Ls^Vs^Rs^(jobs(Ls, Vs),
label(Vs),
maplist(man_profession_rest, Ls, MP, Rs)), MP)).
which yields:
% 124,485 inferences, 0.041 CPU in 0.042 seconds (97% CPU, 3043643 Lips)
MP = [[brown-banker, clark-doctor, jones-architect, smith-lawyer]].
And that's without even requiring that all income levels etc. be different. If you want, you can express this constraint easily by adding:
transpose(Rests, RestsT), maplist(all_different, RestsT)
to this formulation.