在Prolog中模拟窃贼谜题的困难

在Prolog中模拟窃贼谜题的困难,prolog,Prolog,我试图对此进行建模: 三个人中只有一个人,爱丽丝、贝托和卡尔偷了多特菲尔女士的钱。她雇你当侦探顾问。在分别询问他们之后,您有以下信息: 艾丽斯:别相信卡尔。他在撒谎,把钱拿走了 卡尔:贝托在撒谎,但爱丽丝没有拿钱 贝托:卡尔拿了钱。我没拿钱 在收集信息之后,你知道,只要他们中的一个撒谎,他们就在陈述的两个部分都撒谎。而且,如果他们中的一个说了实话,那么他们在陈述的两个部分都说了实话。谁拿了钱 我以类似的方式为它建模。特别是,我在11:34附近用“基于Prolog的”解决方案对其建模,而不是前面介

我试图对此进行建模:

三个人中只有一个人,爱丽丝、贝托和卡尔偷了多特菲尔女士的钱。她雇你当侦探顾问。在分别询问他们之后,您有以下信息:

艾丽斯:别相信卡尔。他在撒谎,把钱拿走了

卡尔:贝托在撒谎,但爱丽丝没有拿钱

贝托:卡尔拿了钱。我没拿钱

在收集信息之后,你知道,只要他们中的一个撒谎,他们就在陈述的两个部分都撒谎。而且,如果他们中的一个说了实话,那么他们在陈述的两个部分都说了实话。谁拿了钱

我以类似的方式为它建模。特别是,我在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。
用于查询。

我是这样做的:

?- 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——我只是想到了一个更好的方法。我会更新的。