这是问题所在:
维克多被谋杀了,亚瑟,伯特伦和卡尔顿都是 犯罪嫌疑人。亚瑟说他没有这样做。他说Bertram是 受害者的朋友,但卡尔顿痛恨受害者。伯特伦说他 在谋杀当天离开了城镇,除此之外他甚至都不知道 那家伙。卡尔顿说他是无辜的,他看到亚瑟和伯特伦 在谋杀案发生之前与受害者在一起。假设每个人 - 除外 可能是凶手 - 说实话,使用解决方案 解决犯罪。
这是我在SWI Prolog中所写的内容
% Facts:
p('Arthur'). % suspect
p('Bertram'). % suspect
p('Carleton'). % suspect
p('Victor'). % victim
% Arthur
says('Arthur', i('Arthur')).
says('Arthur', f('Bertram', 'Victor')).
says('Arthur', ht('Carleton', 'Victor')).
% Bertram
says('Bertram', o('Bertram')).
says('Bertram', nk('Bertram', 'Victor')).
% Carleton
says('Carleton', i('Carleton')).
says('Carleton', t('Arthur', 'Victor')).
says('Carleton', t('Bertram', 'Victor')).
% Rules:
holds(X) :- says(Y, X), \+m(Y).
holds(i(X)) :- p(X), \+m(X).
holds(f(X,Y)) :- p(X), p(Y), holds(f(Y,X)).
holds(f(X,Y)) :- p(X), p(Y), \+holds(nk(X,Y)).
holds(o(X)) :- p(X), p(Y), holds(t(X,Y)).
holds(o(X)) :- p(X), \+m(X).
holds(nk(X,Y)) :- p(X), p(Y), \+holds(nk(Y,X)).
holds(nk(X,Y)) :- p(X), p(Y), \+holds(f(X,Y)).
holds(t(X,Y)) :- p(X), p(Y), holds(t(Y,X)).
holds(t(X,Y)) :- p(X), p(Y), p(Z), holds(t(X,Z)), holds(t(Z,Y)).
m(X) :- p(X).
答案是Bertram,但我继续得到Arthur。不知道我做错了什么。
答案 0 :(得分:1)
我很确定规则会比这简单得多。
例如,假设p(X)始终为真,那意味着m(X) :- p(X).
是什么意思?维克多有话要说吗?
在逻辑中,坚持Occam's Razor至关重要。 编程逻辑它不是一个例外,尽管该术语具有更实际的含义 - 请参阅KISS principle。
我认为我们只能同意谋杀应该是与其他两个人相矛盾的人。只有一个事实是:一个人是否知道维克多。
然后我们可以总结我们对犯罪的了解:
t(a) :- k(b), k(c).
t(b) :- \+ k(b).
t(c) :- k(a), k(b).
k(_).
其中t(X)代表X testimony that
,k(X)代表X known Victor
。
我们真的不知道k(X),那么我们必须添加k(_)。
有了这个,Prolog可以建议:
?- t(X).
X = a ;
X = c.
即。只有a或b才可以。
编辑:因为Prolog在否定时不是主张,所以这是一种征求解决方案的方法:
m(X) :- member(X, [a,b,c]), \+ t(X).
但是我们采取更明确的方法:
如上所示,我们的事实基础也可以表达:而不是分句形式,这导致Prolog 执行的立即可用性:
say(a, know_victim(b, yes)).
say(a, know_victim(c, yes)).
say(b, know_victim(b, no)).
say(c, know_victim(a, yes)).
say(c, know_victim(b, yes)).
现在让我们看看是否某些人说出与其他人相反的信息
liar(I) :-
select(I, [a,b,c], Js),
say(I, Fact),
maplist(negate(Fact), Js).
negate(know_victim(I, X), J) :-
say(J, know_victim(I, Y)),
X \= Y.
产量
?- liar(I).
I = b ;
false.
答案 1 :(得分:0)