Strange warning and computation leads to constraint logic program
First, sorry to post the whole program, but since I don't know if there was a problem, I don't know which parts are irrelevant. These are two slightly different implementations of the same logic puzzle in SWI-Prolog, the first is the second and I cannot find the reason for the failure.
Puzzle:
4 persons are having a diner:
Donna, Doreen, David, Danny
the woman (Donna,Doreen) are sitting vis-a-vis.
the men (David,Danny) are sitting vis-a-vis.
Each of them picked a unique meal and beverage.
1) Doreen sits next to the person that ordered risotto.
2) the salad came with a coke.
3) the person with the lasagna sits vis-a-vis the person with the milk.
4) david never drinks coffee.
5) donna only drinks water.
6) danny had no appetite for risotto.
who ordered the pizza?
I take the following approach
table with positions:
1
4 O 2
3
domain: positions{1,2,3,4}
variables: persons, meals, beverages
First inefficient follow-up implementation:
solution(Pizza, Doreen, Donna, David, Danny) :-
% assignment of unique positions to the variables
unique(Doreen,Donna,David,Danny),
unique(Lasagna,Pizza,Risotto,Salad),
unique(Water,Coke,Coffee,Milk),
% general setting
vis_a_vis(Donna,Doreen),
vis_a_vis(David,Danny),
% the six constraints
next_to(Doreen,Risotto),
Salad = Coke,
vis_a_vis(Lasagna,Milk),
\+ David = Coffee,
Donna = Water,
\+ Danny = Risotto.
unique(X1,X2,X3,X4) :-
pos(X1),
pos(X2),
\+ X1 = X2,
pos(X3),
\+ X1 = X3, \+ X2 = X3,
pos(X4),
\+ X1 = X4, \+ X2 = X4, \+ X3 = X4.
right(1,2).
right(2,3).
right(3,4).
right(4,1).
vis_a_vis(1,3).
vis_a_vis(3,1).
vis_a_vis(2,4).
vis_a_vis(4,2).
next_to(X,Y) :- right(X,Y).
next_to(X,Y) :- right(Y,X).
pos(1).
pos(2).
pos(3).
pos(4).
This works and gives the correct result. But when I try to change the order of the decision procedures to be more efficient (this is the second implementation)
solution(Pizza, Doreen, Donna, David, Danny) :-
% general setting
vis_a_vis(Donna,Doreen),
vis_a_vis(David,Danny),
% the six constraints
Salad = Coke,
vis_a_vis(Lasagna,Milk),
\+ David = Coffee,
Donna = Water,
\+ Danny = Risotto,
% assignment of unique positions to the variables
unique(Doreen,Donna,David,Danny),
unique(Lasagna,Pizza,Risotto,Salad),
unique(Water,Coke,Coffee,Milk).
%% all other predicates are like the ones in the first implementation
When I try to upload a file, I get an unassigned variable warning:
Warning: /home/pizza.pl:28:
Singleton variable in \+: Coffee
and the calculation returns false
. But shouldn't it return the same result? I see no reason for the difference ...
source to share
the warning is due to the fact that Coffe and Risotto are not linked when the negation is done. If you replace \+ David = Coffee,
with David \= Coffee,
, you will avoid the warning, but the solution cannot be calculated. It should be clear that since coffee is unrelated David \ = Coffee always fails. You can use diff / 2, the solution will work and be more efficient. I called solution1 / 2 your first snippet and solution2 / 5 one (using dif / 2):
solution2(Pizza, Doreen, Donna, David, Danny) :-
% general setting
vis_a_vis(Donna,Doreen),
vis_a_vis(David,Danny),
% the six constraints
next_to(Doreen,Risotto), % note: you forgot this one
Salad = Coke,
vis_a_vis(Lasagna,Milk),
dif(David, Coffee),
Donna = Water,
dif(Danny, Risotto),
% assignment of unique positions to the variables
unique(Doreen,Donna,David,Danny),
unique(Lasagna,Pizza,Risotto,Salad),
unique(Water,Coke,Coffee,Milk).
little test:
?- time(aggregate_all(count,solution1(P,A,B,C,D),N)). % 380,475 inferences, 0.058 CPU in 0.058 seconds (100% CPU, 6564298 Lips) N = 8. ?- time(aggregate_all(count,solution2(P,A,B,C,D),N)). % 10,626 inferences, 0.002 CPU in 0.002 seconds (100% CPU, 4738996 Lips) N = 8.
source to share