将逻辑难题转换为谓词演算和 prolog/dlv

Converting logical puzzle into predicate calculus and prolog/dlv

问题是:盐被偷了!好吧,我们发现罪魁祸首要么是毛毛虫, 蜥蜴比尔或柴郡猫。三者经过尝试,做出如下 法庭陈述:

CATERPILLAR: Bill the Lizard ate the salt.
BILL THE LIZARD: That is true!
CHESHIRE CAT: I never ate the salt.

碰巧的是,他们中至少有一个说谎,至少一个说真话。谁吃了 盐?

我确定如果 bill 是真的,那么所有的陈述都是真的,如果 cheshire 是真的,那么所有的都是假的,所以它一定是毛毛虫。

查看谓词演算并对其进行编程,它应该是这样的:

suspect(caterpillar).
suspect(lizard).
suspect(cat).

:- suspect(cat), suspect(lizard).
:- suspect(cat), suspect(caterpillar).
:- suspect(lizard), suspect(caterpillar).

%where these imply not more than one of these can be true or returned in our set

但是在谓词逻辑中进一步描述这一点,我不知道如何描述他们所做的描述或请求。以及如果一个陈述为真如何暗示其他陈述可能为假。

这个谜题的一个好处是你甚至不需要一阶谓词逻辑来建模:使用命题[=24就足够了=] 逻辑,因为嫌疑人是说谎还是说真话可以用一个布尔变量来表示,而陈述本身也只是对布尔变量的陈述。

因此,在使用 Prolog 解决此任务时,请考虑在 布尔值 变量上使用约束求解器。有关详细信息,请参阅

这是一个示例解决方案,使用 SICStus Prolog 或 SWI:

:- use_module(library(clpb)).

solution(Pairs) :-
        Suspects = [_Caterpillar,Lizard,Cat],
        pairs_keys_values(Pairs, [caterpillar,lizard,cat], Suspects),
        Truths = [CaterpillarTrue,LizardTrue,CatTrue],
        % exactly one of them ate the salt
        sat(card([1], Suspects)),
        % the statements
        sat(CaterpillarTrue =:= Lizard),
        sat(LizardTrue =:= Lizard),
        sat(CatTrue =:= ~Cat),
        % at least one of them tells the truth:
        sat(card([1,2,3], Truths)),
        % at least one of them lies:
        sat(card([1,2,3], [~CaterpillarTrue,~LizardTrue,~CatTrue])).

由此无需搜索即可轻松确定唯一解:

?- solution(Pairs).
Pairs = [caterpillar-1, lizard-0, cat-0].