在Prolog中解决爱因斯坦之谜

Bel*_*lgi 4 prolog zebra-puzzle

我正试图在Prolog中解决爱因斯坦之谜.

我对我编写的程序有困难,基本方法是添加所有约束,让Prolog找出唯一可能的解决方案.

问题是Prolog找到了0个解决方案.我已经隔离了使程序从给定解决方案转到没有解决方案的约束,但我不明白为什么.

/*There are five houses*/
exists(A, list(A,_,_,_,_)).
exists(A, list(_,A,_,_,_)).
exists(A, list(_,_,A,_,_)).
exists(A, list(_,_,_,A,_)).
exists(A, list(_,_,_,_,A)).

middle_house(A, list(_,_,A,_,_)).

first_house(A, list(A,_,_,_,_)).

nextTo(A, B, list(B,A,_,_,_)).
nextTo(A, B, list(_,B,A,_,_)).
nextTo(A, B, list(_,_,B,A,_)).
nextTo(A, B, list(_,_,_,B,A)).
nextTo(A, B, list(A,B,_,_,_)).
nextTo(A, B, list(_,A,B,_,_)).
nextTo(A, B, list(_,_,A,B,_)).
nextTo(A, B, list(_,_,_,A,B)).

/* each statement will be described using the clues 
house conatins: Color,Owner, Drinks, Smokes, Pet*/
riddle(Houses):-
    /*exists(house(red, englishman, _,_,_),Houses),*/
    nextTo(house(_,norwegian,_,_,_), house(blue,_,_,_,_), Houses),
    exists(house(_,spanish,_,_, dog), Houses),
    exists(house(green, _, coffee, _,_), Houses),
    exists(house(_, ukrain, tea,_,_), Houses),
    nextTo(house(white,_,_,_,_), house(green,_,_,_,_), Houses),
    exists(house(_,_,_,marlbero, cat),Houses),
    exists(house(yellow,_,_,time,_), Houses),
    middle_house(house(_,_,milk,_,_), Houses),
    first_house(house(_,norwegian,_,_,_), Houses),
    nextTo(house(_,_,_,_,fox), house(_,_,_,montena,_), Houses),
    nextTo(house(_,_,_,time,_), house(_,_,_,_,horse), Houses),
        exists(house(_,_,orange,lucky,_), Houses),
    exists(house(_,japanese,parlament,_), Houses).
Run Code Online (Sandbox Code Playgroud)

目前的解决方案是:

?- riddle(Houses).
Houses = list( house(green, norwegian, coffee, marlbero, cat),
               house(white, spanish, orange, lucky, dog),
               house(yellow, norwegian, milk, time, fox),
               house(blue, ukrain, tea, montena, horse),
               house(_G7257, japanese, parlament, _G7260)).
Run Code Online (Sandbox Code Playgroud)

如果我取消注释第一行,那么同一个语句返回false.

我想帮助理解为什么会这样.我注意到,在部分解决方案中,挪威人出现了两次,这可能表明问题.

fal*_*lse 6

以下是如何为自己解决此问题的一般方法.实际上,你真的开始了一个非常有希望的方向:你试图删除目标.但那么,谁在你的情况下有过错呢?您注释掉的线还是其他线?你不能肯定地说,因为结果程序已经有效了.但是有一种非常相似且更有前途的方法:尝试尽可能多地概括你的程序,使它仍然失败.通过这种方式,您将获得一个负责故障的较小程序.也就是说,在剩余的可见部分内必须是一个错误!

这是我通过删除目标(在前面添加*)和用_替换一些术语而得到的.

:- initialization(riddle(_Sol)).
:- op(950, fy, *).
*_.

riddle(Houses):-
    exists(house(red, _/* englishman */, _,_,_),Houses),
    nextTo(house(_,_/* norwegian */,_,_,_), house(blue,_,_,_,_), Houses),
    * exists(house(_,spanish,_,_, dog), Houses),
    * exists(house(green, _, coffee, _,_), Houses),
    * exists(house(_, ukrain, tea,_,_), Houses),
    nextTo(house(white,_,_,_,_), house(green,_,_,_,_), Houses),
    * exists(house(_,_,_,marlbero, cat),Houses),
    exists(house(yellow,_,_,_/* time */,_), Houses),
    * middle_house(house(_,_,milk,_,_), Houses),
    * first_house(house(_,norwegian,_,_,_), Houses),
    * nextTo(house(_,_,_,_,fox), house(_,_,_,montena,_), Houses),
    * nextTo(house(_,_,_,time,_), house(_,_,_,_,horse), Houses),
    * exists(house(_,_,orange,lucky,_), Houses),
    exists(house(_,_/* japanese */,_/* parlament */,_), Houses).

这个片段仍然失败,因此错误必须在程序的可见部分.

似乎所有的房屋颜色都是必不可少的.只有一个目标根本不包含任何房屋颜色......看到了吗?