我正在为此simple logic puzzle建模:
三个人中只有一个,爱丽丝(Alice),贝托(Beto)和卡尔(Carl)偷了Doubtfire女士的钱。她雇用您担任顾问侦探。在对它们进行讯问之后,您将拥有以下内容:
爱丽丝:不要相信卡尔。他在撒谎,他拿了钱。
卡尔:贝托在撒谎,但爱丽丝没有拿钱。
贝托:卡尔拿了钱。我没有拿钱。
收集信息后,您知道,只要其中一个说谎,他们就会对陈述的两个部分都撒谎。同样,如果其中一个人讲真话,他们在陈述的两个部分都讲真话。谁拿了钱?
我以与this video about Knights and Knaves类似的方式对其进行建模。特别是,我使用11:34附近的“基于Prolog”解决方案,而不是之前介绍的基于SAT解算器的模型进行建模。我对false
关系做了一些修改。
says(guilty_liar, S) :- not(S).
says(innocent_liar, S) :- not(S).
says(guilty_but_honest, S) :- S.
says(innocent_and_honest, S) :- S.
false(A = guilty_liar) :- A = innocent_and_honest.
false(A = guilty_but_honest) :- A = innocent_liar.
false(A = innocent_liar) :- A = guilty_but_honest.
false(A = innocent_and_honest) :- A = guilty_liar.
false((P ; Q)) :- false(P), false(Q) .
false((P , Q)) :- ( false(P) ; false(Q) ).
然后,我将进行以下查询:
?- [burglar].
true.
?- says(A, (C = guilty_liar)), says(C, ((B = guilty_liar ; B = innocent_liar), (A = innocent_liar ; A = innocent_and_honest ))), says(B, ((C = guilty_liar ; C = guilty_but_honest) , (B = innocent_and_honest ; B = innocent_liar))).
A = guilty_but_honest,
C = B, B = guilty_liar ;
A = guilty_but_honest,
C = guilty_liar,
B = innocent_and_honest ;
false.
尽管我期望的不仅仅是正确的解决方案(因为我没有放下所有限制条件),但是我期望正确的解决方案会出现。也就是说,爱丽丝天真无邪,但撒谎,卡尔讲真话,贝托是有罪的骗子。
此外,这是第二条查询,分为多行,以方便阅读:
says(A, (C = guilty_liar)),
says(C, ((B = guilty_liar ; B = innocent_liar), (A = innocent_liar ; A = innocent_and_honest ))),
says(B, ((C = guilty_liar ; C = guilty_but_honest) , (B = innocent_and_honest ; B = innocent_liar))).
我很困惑为什么没有显示正确的解决方案。
更新
我愚蠢地使用了not
而不是我定义的false
函数,但是,即使用not(S)
退出false(S)
也会得到false.
的查询
答案 0 :(得分:1)
我是这样做的:
?- People = [alice(_, _), beto(_, _), carl(_, _)], alice(People), carl(People), beto(People), write(People), nl, fail.
alice(People) :-
member(alice(honest, innocent), People),
member(carl(liar, thief), People).
alice(People) :-
member(alice(liar, _), People),
member(carl(honest, innocent), People).
carl(People) :-
member(carl(honest, _), People),
member(beto(liar, _), People),
member(alice(_, innocent), People).
carl(People) :-
member(carl(liar, _), People),
member(beto(honest, _), People),
member(alice(_, thief), People).
beto(People) :-
member(beto(honest, innocent), People),
member(carl(_, thief), People).
beto(People) :-
member(beto(liar, thief), People),
member(carl(_, innocent), People).
结果[alice(liar, innocent), beto(liar, thief), carl(honest, innocent)]
。
这稍微简单一些:
alice([alice(honest, innocent), beto(_, _), carl(liar, thief)]).
alice([alice(liar, _), beto(_, _), carl(honest, innocent)]).
carl([alice(_, innocent), beto(liar, _), carl(honest, _)]).
carl([alice(_, thief), beto(honest, _), carl(liar, _)]).
beto([alice(_, _), beto(honest, innocent), carl(_, thief)]).
beto([alice(_, _), beto(liar, thief), carl(_, innocent)]).
答案 1 :(得分:1)
这对我来说似乎非常可疑:says(A, (C = guilty_liar))
。
可能存在一个约束,即两个语句都为true或均为false,因此这里只有一个语句。您认为您的逻辑能够正确处理此问题?
无论如何,这是我天真的解决方案:-)为每个命题创建一个true / false变量,并表达这些变量的有效值的所有约束。
true_or_false(X) :- X = true.
true_or_false(X) :- X = false.
bool_to_int(true, 1).
bool_to_int(false, 0).
true_or_false_list([]).
true_or_false_list([V | T]) :- true_or_false(V), true_or_false_list(T).
solution(AliceCorrect, CarlCorrect, BetoCorrect,
AliceThief, CarlThief, BetoThief) :-
true_or_false_list([AliceCorrect, CarlCorrect, BetoCorrect,
AliceThief, CarlThief, BetoThief]),
% Alice statement.
AliceCorrect \= CarlCorrect,
AliceCorrect = CarlThief,
% Carl statement.
CarlCorrect \= BetoCorrect,
CarlCorrect \= AliceThief,
% Beto Statement.
BetoCorrect = CarlThief,
BetoCorrect \= BetoThief,
% There can be only one thief.
bool_to_int(AliceThief, AliceThiefInt),
bool_to_int(CarlThief, CarlThiefInt),
bool_to_int(BetoThief, BetoThiefInt),
1 is AliceThiefInt + CarlThiefInt + BetoThiefInt.
贝托是个小偷。