在Prolog中模拟窃贼谜题的困难
我试图对此进行建模: 三个人中只有一个人,爱丽丝、贝托和卡尔偷了多特菲尔女士的钱。她雇你当侦探顾问。在分别询问他们之后,您有以下信息: 艾丽斯:别相信卡尔。他在撒谎,把钱拿走了 卡尔:贝托在撒谎,但爱丽丝没有拿钱 贝托:卡尔拿了钱。我没拿钱 在收集信息之后,你知道,只要他们中的一个撒谎,他们就在陈述的两个部分都撒谎。而且,如果他们中的一个说了实话,那么他们在陈述的两个部分都说了实话。谁拿了钱 我以类似的方式为它建模。特别是,我在11:34附近用“基于Prolog的”解决方案对其建模,而不是前面介绍的基于SAT解算器的解决方案。我对在Prolog中模拟窃贼谜题的困难,prolog,Prolog,我试图对此进行建模: 三个人中只有一个人,爱丽丝、贝托和卡尔偷了多特菲尔女士的钱。她雇你当侦探顾问。在分别询问他们之后,您有以下信息: 艾丽斯:别相信卡尔。他在撒谎,把钱拿走了 卡尔:贝托在撒谎,但爱丽丝没有拿钱 贝托:卡尔拿了钱。我没拿钱 在收集信息之后,你知道,只要他们中的一个撒谎,他们就在陈述的两个部分都撒谎。而且,如果他们中的一个说了实话,那么他们在陈述的两个部分都说了实话。谁拿了钱 我以类似的方式为它建模。特别是,我在11:34附近用“基于Prolog的”解决方案对其建模,而不是前面介
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。
用于查询。我是这样做的:
?- 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([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)]).
这看起来很可疑:
说(A,(C=有罪的骗子)
。
假设有一个约束,即两个语句都是真的或都是假的,这里只有一个语句。你认为你的逻辑处理得对吗
无论如何,这是我的简单解决方案:-)为每个命题创建一个真/假变量,并用这些变量的therms表示所有约束
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.
贝托是个小偷。你解决了这个问题吗?如果是这样,不要在问题的底部添加答案。发布你自己的答案。@Enigmativity不,它没有解决。我刚刚意识到一个错误,那就是我使用了
not(S)
而不是false(S)
,当使用false(S)
而不是false时,没有找到解决方案。(应该至少有一个解决方案)有趣的是,我不知道你可以用这种方式来解释Prolog。所以,alice(诚实,无辜)
读起来就像诚实和无辜与alice(的特征)有关?然后,爱丽丝(人们)
读到了爱丽丝的世界形象,爱丽丝是一个诚实和无辜的人,卡尔是一个骗子和小偷?我猜是这样,但在这种情况下Alice liar和诚实案例都需要处理,这似乎很奇怪。@Dair-我使用了Alice/1
作为谓词,使用Alice/2
作为数据结构alice/1
有两条规则,因此,如果第一条规则失败,将尝试第二条规则-这只是一条或
。然后,每一条规则都只表达了一整套条件——一个和@Dair——我只是想到了一个更好的方法。我会更新的。