/***********************************************************
who_killed_agatha.pi
from Constraint Solving and Planning with Picat, Springer
by Neng-Fa Zhou, Hakan Kjellerstrand, and Jonathan Fruhman
***********************************************************/
import cp.
main =>
L = find_all(Killer, who_killed_agatha(Killer)),
println(killer=L).
who_killed_agatha(Killer) =>
% Agatha, the butler, and Charles live in Dreadsbury Mansion,
% and are the only ones to live there.
N = 3,
Agatha = 1,
Butler = 2,
Charles = 3,
% The killer is one of the three.
Killer :: [Agatha,Butler,Charles],
% Define the Hates and Richer Boolean matrices
Hates = new_array(N,N),
Hates :: 0..1,
Richer = new_array(N,N),
Richer :: 0..1,
% A killer always hates, and is no richer than his victim.
foreach (I in 1..N)
Killer #= I #=> Hates[I, Agatha] #= 1,
Killer #= I #=> Richer[I, Agatha] #= 0
end,
% Define the concept of "richer":
% nobody is richer than him-/herself
foreach (I in 1..N)
Richer[I,I] #= 0
end,
% if I is richer than J, then J is not richer than I
foreach (I in 1..N, J in 1..N, I != J)
Richer[I,J] #= 1 #<=> Richer[J,I] #= 0
end,
% Charles hates nobody that Agatha hates.
foreach (I in 1..N)
Hates[Agatha, I] #= 1 #=> Hates[Charles, I] #= 0
end,
% Agatha hates everybody except the butler.
Hates[Agatha, Butler] #= 0,
Hates[Agatha, Charles] #= 1,
Hates[Agatha, Agatha] #= 1,
% The butler hates everyone not richer than Aunt Agatha.
foreach (I in 1 ..N)
Richer[I, Agatha] #= 0 #=> Hates[Butler, I] #= 1
end,
% The butler hates everyone whom Agatha hates.
foreach (I in 1..N)
Hates[Agatha, I] #= 1 #=> Hates[Butler, I] #= 1
end,
% Nobody hates everyone.
foreach (I in 1..N)
sum([Hates[I,J] : J in 1..N]) #=< 2
end,
% Who killed Agatha?
Vars = [Killer] ++ Hates ++ Richer,
solve(Vars).