斑马拼图的真相表

时间:2017-05-19 23:42:51

标签: logic computer-science boolean-logic truthtable zebra-puzzle

我正在阅读"计算机科学蒸馏"书,我遇到了麻烦。作者建议解决爱因斯坦"斑马拼图"通过真值表,但我无法弄清楚如何。我无法找到起始条件和变量。您对最小的桌子有什么想法吗?我想我只能创建一个6 ^ 6版本

3 个答案:

答案 0 :(得分:4)

我是OP提到的那本书的作者。我并不是说读者只使用 一个大的真值表来解决斑马拼图,而是使用它作为一种工具来检测永远不会发生的情况,并更好地指导探索过程。

使用表示房屋/属性状态的变量的大型真值表,您可以发现一个变量,如果为真,则意味着许多相关状态。最好是测试这些变量以找出逻辑矛盾而不是简单地强制所有变量。

我写了一篇详细的博客文章,解释了如何使用简单的推论和布尔代数来解决Zebra谜题,在这里:https://code.energy/solving-zebra-puzzle/

答案 1 :(得分:1)

典型的谜语可以被视为k×n矩阵,然后用k×n 2 布尔变量编码,如here。如果 - 并且仅当 - 矩阵中的(i,j)-entry具有值m时,则将变量P ijm 视为真。

显然,你需要一个SAT求解器来解决以这种方式编码的谜语。我想作者建议你讽刺地使用真值表,或者出于教学原因,或者他/她要求你实施SAT求解器中使用的技术。

为了减少所涉及的“术语”的数量,必须在一阶逻辑的(可判定的)片段中对该难题进行建模,例如, Horn子句(Prolog)或描述逻辑(OWL reasoners)。

术语数量的这种“命题式爆炸”的另一个例子是命题列表原则。

答案 2 :(得分:0)

下面的MiniZinc脚本显示了如何根据25决策变量对斑马拼图进行编码。它们每个都有1..5的值。就布尔变量而言,将需要25*3 = 75位。

@Stanislav Kralin建议的直接布尔编码需要5*5*5 = 125布尔决策变量。

可以找到更优雅的版本here。它表现出相同数量的决策变量。

%  Zebra Puzzle in MiniZinc
%  https://en.wikipedia.org/wiki/Zebra_Puzzle

%  for all_different()
include "globals.mzn";

%  Number of houses (cf. constraint 1.)
int: n = 5;
set of int: House = 1..5;

%  Nationalities
var House: English;
var House: Spaniard;
var House: Ukranian;
var House: Norwegian;
var House: Japanese;

%  Beverages
var House: Coffee;
var House: Tea;
var House: Milk;
var House: Orange_Juice;
var House: Water;

%  Pets
var House: Dog;
var House: Horse;
var House: Snail;
var House: Fox;
var House: Zebra;

%  House colors
var House: Red;
var House: Yellow;
var House: Ivory;
var House: Blue;
var House: Green;

%  Cigarette brands
var House: Old_Gold;
var House: Kools;
var House: Chesterfield;
var House: Lucky_Strike;
var House: Parliaments;

%  Explicit constraints
% 1. There are five houses.

% 2. The Englishman lives in the red house.
constraint English = Red;

% 3. The Spaniard owns the dog.
constraint Spaniard = Dog;

% 4. Coffee is drunk in the green house.
constraint Coffee = Green;

% 5. The Ukranian drinks tea.
constraint Ukranian = Tea;

% 6. The green house is immediately to the right of the ivory house.
constraint Green = (Ivory + 1);

% 7. The Old Gold smoker owns snails.
constraint Old_Gold = Snail;

% 8. Kools are smoked in the yellow house.
constraint Kools = Yellow;

% 9. Milk is drunk in the middle house.
constraint Milk = (n + 1)/2;

% 10. The Norwegian lives in the first house.
constraint Norwegian = 1;

% 11. The man who smokes Chesterfields lives in the house next to the man with the fox.
constraint abs(Chesterfield - Fox) = 1;

% 12. Kools are smoked in the house next to the house where the horse is kept.
constraint abs(Kools - Horse) = 1;

% 13. The Lucky Strike smoker drinks orange juice.
constraint Lucky_Strike = Orange_Juice;

% 14. The Japanese smokes Parliaments.
constraint Japanese = Parliaments;

% 15. The Norwegian lives next to the blue house.
constraint abs(Norwegian - Blue) = 1;

%  Implicit constraints
%  each of the five houses is painted a different color
constraint all_different([Red, Blue, Yellow, Green, Ivory]);

%  inhabitants are of different national extractions
constraint all_different([English, Spaniard, Ukranian, Norwegian, Japanese]);

%  inhabitants own different pets
constraint all_different([Dog, Horse, Snail, Fox, Zebra]);

%  inhabitants drink different beverages 
constraint all_different([Coffee, Tea, Milk, Orange_Juice, Water]);

%  inhabitants smoke different brands of American cigarets [sic]
constraint all_different([Old_Gold, Kools, Chesterfield, Lucky_Strike, Parliaments]);

solve satisfy;

function string: take(int: h, array[1..n-1] of House: x, array[House] of string: s) =
  if x[1] = h then s[1] 
  elseif x[2] = h then s[2] 
  elseif x[3] = h then s[3] 
  elseif x[4] = h then s[4] 
  else s[5] endif;

output ["\nColor       "] ++
       [ take(h, [fix(Red), fix(Blue), fix(Green), fix(Ivory)], 
                 ["red          ", "blue         ", "green        ", "ivory        ", "yellow       "])| h in House] ++
       ["\nNationality "] ++
       [ take(h, [fix(English), fix(Spaniard), fix(Ukranian), fix(Norwegian)],
                 ["English      ", "Spaniard     ", "Ukranian     ", "Norwegian    ", "Japanese     "])| h in House] ++
       ["\nPet         "] ++
       [ take(h, [fix(Dog), fix(Horse), fix(Snail), fix(Fox)],
                 ["Dog          ", "Horse        ", "Snail        ", "Fox          ", "Zebra        "])| h in House] ++
       ["\nBeverage    "] ++
       [ take(h, [fix(Coffee), fix(Tea), fix(Milk), fix(Orange_Juice)],
                 ["Coffee       ", "Tea          ", "Milk         ", "Orange Juice ", "Water        "])| h in House] ++
       ["\nCigarette   "] ++
       [ take(h, [fix(Old_Gold), fix(Kools), fix(Chesterfield), fix(Lucky_Strike)],
                 ["Old Gold     ", "Kools        ", "Chesterfield ", "Lucky Strike ", "Parliaments  "])| h in House];