用Prolog中的约束和置换法解谜

用Prolog中的约束和置换法解谜,prolog,zebra-puzzle,Prolog,Zebra Puzzle,我被要求使用Prolog解决一个类似于斑马难题的难题。相反,我试图找到吃馅饼的人的国籍。我知道对于这个问题有不同的解决方案,但是我试图通过使用约束和排列来解决这个难题。但是,运行pie_eater谓词返回false,并且在跟踪代码时不会停止运行 约束列表如下所示: 1) the Irish person lives next to the yellow house 2) the person who likes donuts lives next to the person who enjoy

我被要求使用Prolog解决一个类似于斑马难题的难题。相反,我试图找到吃馅饼的人的国籍。我知道对于这个问题有不同的解决方案,但是我试图通过使用约束和排列来解决这个难题。但是,运行pie_eater谓词返回false,并且在跟踪代码时不会停止运行

约束列表如下所示:

1) the Irish person lives next to the yellow house

2) the person who likes donuts lives next to the person who enjoys embroidery

3) the person who enjoys trainspotting lives next to the one who likes pizza

4) the person who enjoys pachinko likes beets

5) the Czech lives in the purple house

6) the person living in the center house listens to grunge

7) the person who enjoys glassblowing listens to hip hop

8) the American likes tofu

9) the Dutch person listens to J-Pop

10) the pink house's owner listens to country

11) the owner of the green house enjoys embroidery

12) the Irish person lives in the first house

13) the pink house is on the left of the orange house

14) the Japanese person enjoys gardening

15) the person who enjoys trainspotting has a neighbor who listens to jazz
%who eats pie
pie_eater(PieEater) :-
        puzzle(X),
        member(house(PieEater, _, _, _, pie), X).


puzzle(Street) :- 

        Street = [H1, H2, H3, H4, H5], %street of 5 houses

        %vars for permutation
        H1 = house(Nat1, Col1, Mus1, Hob1, Food1),
        H2 = house(Nat2, Col2, Mus2, Hob2, Food2),
        H3 = house(Nat3, Col3, Mus3, Hob3, Food3),
        H4 = house(Nat4, Col4, Mus4, Hob4, Food4),
        H5 = house(Nat5, Col5, Mus5, Hob5, Food5),

        % facts
        nextto(house(irish, _, _, _, _), house(_, yellow, _, _, _), Street), %irish next to yellow house
        nextto(house(_, _, _, _, donuts), house(_, _, _, embroidery, _), Street), %donut next to embrodier lover
        nextto(house(_, _, _, trainspotting, _), house(_, _, _, _, pizza), Street),  %trainspotting next to pizza ouse      
        member(house(_, _, _, pachinko, beets), Street), %pachinko person eats beets
        member(house(czech, purple, _, _, _), Street), %czech person lives in purple house
        [_, _, house(_, _, grunge, _, _), _, _] = Street, %middle house listens to grunge
        member(house(_, _, hiphop, glassblowing, _), Street), %hiphop lover likes glassblowing
        member(house(american, _, _, _, tofu), Street), %american likes tofu
        member(house(dutch, _, jpop, _, _), Street), %dutch person likes jpop
        member(house(_, pink, country, _, _), Street),  %pink house person likes country music
        member(house(_, green, _, embroidery, _), Street), %green house person likes embroidery
        [house(irish, _, _, _, _), _, _, _, _] = Street, %irish person in first house
        leftof(house(_, pink, _, _, _),house(_, orange, _, _, _), Street),  %pink house left of orange house
        member(house(japanese, _, _, gardening, _), Street), %japanese person likes gardening
        member(house(_, _, jazz, trainspotting, _), Street), %trainspotting person likes jazz
        member(house(_, _, _, _, pie), Street), %one person likes pie

        %permutation guesses
        permutation([irish, czech, american, dutch, japanese],[Nat1, Nat2, Nat3, Nat4, Nat5]), %nat permutations
        permutation([yellow, purple, pink, green, orange],[Col1, Col2, Col3, Col4, Col5]), %color permutations
        permutation([grunge, hiphop, jpop, country, jazz],[Mus1, Mus2, Mus3, Mus4, Mus5]), %music permutation
        permutation([trainspotting, pachinko, glassblowing, embroidery, gardening],[Hob1, Hob2, Hob3, Hob4, Hob5]), %hobby permutation
        permutation([donuts, beets, pizza, tofu, pie],[Food1, Food2, Food3, Food4, Food5]). %food permutation

 %defining other predicates to help solve puzzle
 nextto(X, Y, List) :- leftof(X, Y, List). 
 nextto(X, Y, List) :- leftof(Y, X, List).

 %check if left of
 leftof(L, R, [L,R|_]).
 leftof(L, R, [_ | Rest]) :- leftof(L, R, Rest).
在我的代码中,我定义了一个包含5栋房屋的列表Street。然后,我为列表中每个元素的每个对应形容词定义了变量,以用于排列猜测。我将每个约束转换为代码。为了得到答案,我为每所房子的每一组变量创建了排列。 在底部,我定义了谓词leftofnextto,以满足问题的一些约束条件

守则如下:

1) the Irish person lives next to the yellow house

2) the person who likes donuts lives next to the person who enjoys embroidery

3) the person who enjoys trainspotting lives next to the one who likes pizza

4) the person who enjoys pachinko likes beets

5) the Czech lives in the purple house

6) the person living in the center house listens to grunge

7) the person who enjoys glassblowing listens to hip hop

8) the American likes tofu

9) the Dutch person listens to J-Pop

10) the pink house's owner listens to country

11) the owner of the green house enjoys embroidery

12) the Irish person lives in the first house

13) the pink house is on the left of the orange house

14) the Japanese person enjoys gardening

15) the person who enjoys trainspotting has a neighbor who listens to jazz
%who eats pie
pie_eater(PieEater) :-
        puzzle(X),
        member(house(PieEater, _, _, _, pie), X).


puzzle(Street) :- 

        Street = [H1, H2, H3, H4, H5], %street of 5 houses

        %vars for permutation
        H1 = house(Nat1, Col1, Mus1, Hob1, Food1),
        H2 = house(Nat2, Col2, Mus2, Hob2, Food2),
        H3 = house(Nat3, Col3, Mus3, Hob3, Food3),
        H4 = house(Nat4, Col4, Mus4, Hob4, Food4),
        H5 = house(Nat5, Col5, Mus5, Hob5, Food5),

        % facts
        nextto(house(irish, _, _, _, _), house(_, yellow, _, _, _), Street), %irish next to yellow house
        nextto(house(_, _, _, _, donuts), house(_, _, _, embroidery, _), Street), %donut next to embrodier lover
        nextto(house(_, _, _, trainspotting, _), house(_, _, _, _, pizza), Street),  %trainspotting next to pizza ouse      
        member(house(_, _, _, pachinko, beets), Street), %pachinko person eats beets
        member(house(czech, purple, _, _, _), Street), %czech person lives in purple house
        [_, _, house(_, _, grunge, _, _), _, _] = Street, %middle house listens to grunge
        member(house(_, _, hiphop, glassblowing, _), Street), %hiphop lover likes glassblowing
        member(house(american, _, _, _, tofu), Street), %american likes tofu
        member(house(dutch, _, jpop, _, _), Street), %dutch person likes jpop
        member(house(_, pink, country, _, _), Street),  %pink house person likes country music
        member(house(_, green, _, embroidery, _), Street), %green house person likes embroidery
        [house(irish, _, _, _, _), _, _, _, _] = Street, %irish person in first house
        leftof(house(_, pink, _, _, _),house(_, orange, _, _, _), Street),  %pink house left of orange house
        member(house(japanese, _, _, gardening, _), Street), %japanese person likes gardening
        member(house(_, _, jazz, trainspotting, _), Street), %trainspotting person likes jazz
        member(house(_, _, _, _, pie), Street), %one person likes pie

        %permutation guesses
        permutation([irish, czech, american, dutch, japanese],[Nat1, Nat2, Nat3, Nat4, Nat5]), %nat permutations
        permutation([yellow, purple, pink, green, orange],[Col1, Col2, Col3, Col4, Col5]), %color permutations
        permutation([grunge, hiphop, jpop, country, jazz],[Mus1, Mus2, Mus3, Mus4, Mus5]), %music permutation
        permutation([trainspotting, pachinko, glassblowing, embroidery, gardening],[Hob1, Hob2, Hob3, Hob4, Hob5]), %hobby permutation
        permutation([donuts, beets, pizza, tofu, pie],[Food1, Food2, Food3, Food4, Food5]). %food permutation

 %defining other predicates to help solve puzzle
 nextto(X, Y, List) :- leftof(X, Y, List). 
 nextto(X, Y, List) :- leftof(Y, X, List).

 %check if left of
 leftof(L, R, [L,R|_]).
 leftof(L, R, [_ | Rest]) :- leftof(L, R, Rest).
盯着我的代码看了几个小时,我觉得它应该可以工作。然而,鉴于我已经定义了所有的约束条件,我仍然不明白为什么我不能生成正确的排列。在这一点上,我被卡住了


我自己做这个问题,我相信日本人就是答案。

约束15没有正确表示。改成

nextto(house(_, _, _, trainspotting, _), house(_, _, jazz, _, _), Street)

允许代码工作。

使用debbuger运行代码时,这部分似乎从未成功过



    member(house(_, _, jazz, trainspotting, _), Street), 

调用此函数时,变量的内容为:

 

     H1 = house(irish, green, Mus1, embroidery, pizza)
     H2 = house(dutch, yellow, jpop, trainspotting, donuts)
     H3 = house(czech, purple, grunge, pachinko, beets)
     H4 = house(japanese, pink, country, gardening, Food4)
     H5 = house(american, orange, hiphop, glassblowing, tofu)

这些信息有用吗? Derpnalday的建议可能是正确的(我不知道为什么他的答案被低估了。)

顺便说一下,我曾经用clpfd解决了另一个斑马问题

1962年,以下版本的拼图出现在国际人寿杂志上:

有五栋房子。 英国人住在红房子里。 这条狗是西班牙人的。 咖啡是在温室里喝的。 乌克兰人喝茶。 绿屋紧靠象牙屋的右边。 老烟鬼有蜗牛。 库尔人在黄房子里抽烟。 牛奶在中间的房子里喝醉了。 挪威人住在第一所房子里。 抽切斯特菲尔德烟的人住在和狐狸在一起的人旁边的房子里。 库尔人在养马的房子旁边的房子里抽烟。 幸运罢工的吸烟者喝橙汁。 日本人在议会中吸烟。 挪威人住在蓝房子旁边。 现在,谁喝水?谁拥有斑马

为了清晰起见,必须补充一点,这五栋房子中的每栋都漆成了不同的颜色,它们的居民来自不同的国家,拥有不同的宠物,喝不同的饮料,抽不同品牌的美国雪茄[sic]。还有一件事:在声明6中,权利意味着你的权利

:-使用_模块(库(clpfd))。
斑马线:-
%左------->右
豪斯=[Color1,Color2,Color3,Color4,Color5],
Pet=[Pet1,Pet2,Pet3,Pet4,Pet5],
比赛=[Race1,Race2,Race3,Race4,Race5],
饮料=[Bev1,Bev2,Bev3,Bev4,Bev5],
烟雾=[Cig1、Cig2、Cig3、Cig4、Cig5],
%比赛1:英语2:西班牙人3:乌克兰人4:挪威人5:日本人
%室内颜色1:红色2:绿色3:象牙色4:黄色5:蓝色
%宠物1:狗2:蜗牛3:狐狸4:马5:斑马
%饮料1:咖啡2:茶3:牛奶4:橙汁5:水
%烟雾1:老金2:库尔3:切斯特菲尔德4:幸运之星5:议会
所有不同(房屋),%房屋
所有不同(宠物),%Pet
所有不同(种族),%国家/地区
所有不同(饮料),%饮料
所有不同(烟雾),%烟雾
第1至第5页,
Pet ins 1..5,
第1至5节比赛,
饮料1..5,
烟雾1..5,
%英国人住在红房子里。
比赛1#=1#颜色1#=1,
比赛2#=1#颜色2#=1,
赛车3#=1#彩色3#=1,
比赛4#=1#颜色4#=1,
赛车5#=1#彩色5#=1,
%西班牙人(2)拥有这条狗(1)。
比赛1#=2#Pet1#=1,
比赛2#=2#Pet2#=1,
比赛3#=2#Pet3#=1,
比赛4#=2#Pet4#=1,
比赛5#=2#Pet5#=1,
%咖啡(1)在温室(2)中饮用。
Bev1#=1#颜色1#=2,
Bev2#=1#颜色2#=2,
Bev3#=1#颜色3#=2,
Bev4#=1#颜色4#=2,
Bev5#=1#颜色5#=2,
%乌克兰人(3)喝茶(2)。
比赛1#=3#Bev1#=2,
比赛2#=3#Bev2#=2,
比赛3#=3#Bev3#=2,
比赛4#=3#比4#=2,
竞赛5#=3#Bev5#=2,
%绿屋(2)紧靠象牙屋(3)的右边。
颜色1#=3#颜色2#=2,
颜色2#=3#颜色3#=2,
颜色3#=3#颜色4#=2,
颜色4#=3#颜色5#=2,
%所以,温室(2)不是最左边的。
颜色1\\=2,
%老金烟民有蜗牛。
Cig1#=1#Pet1#=2,
Cig2#=1#Pet2#=2,
Cig3#=1#Pet3#=2,
Cig4#=1#Pet4#=2,
Cig5#=1#Pet5#=2,
%库尔人在黄色的房子里抽烟。
Cig1#=2#颜色1#=4,
Cig2#=2#颜色2#=4,
Cig3#=2#颜色3#=4,
Cig4#=2#颜色4#=4,
Cig5#=2#颜色5#=4,
%牛奶(3)在中间的房子里喝醉了。
Bev3#=3,
%挪威人住在第一栋房子里。(我假设“第一”是指最左边的)
竞赛1#=4,
%抽切斯特菲尔德烟的人住在养狐狸的人旁边的房子里。
(Cig1#=3#/\Pet2#=3)#\/
(Cig2#=3#/\Pet3#=3)#\/
(Cig3#=3#/\Pet4#=3)#\/
(Cig4#=3#/\Pet5#=3)#\/
(Pet1#=3#/\Cig2#=3)#\/
(Pet2#=3#/\Cig3#=3)#\/
(Pet3#=3#/\Cig4#=3)#\/
(Pet4#=3#/\Cig5#=3),
%库尔(2)在养马(4)的房子旁边的房子里吸烟。
(Cig1#=2#/\Pet2#=4)#\/
(Cig2#=2#/\Pet3#=4)#\/
(Cig3#=2#/\Pet4#=4)#\/
(Cig4#=2#/\Pet5#=4)#\/
(Pet1#=4#/\Cig2#=2)#\/
(Pet2#=4#/\Cig3#=2)#\/
(Pet3#=4#/\Cig4#=2)#\/
(Pet4#=4#/\Cig5#=2),
%幸运之星吸烟者喝橙汁。
Cig1#=4#Bev1#=4,
Cig2#=4#Bev2#=4,
Cig3#=4#Bev3#=4,
Cig4#=4#Bev4#=4,
Cig5#=4#Bev5#=4,
%日本议会吸烟。
比赛1#=5#Cig1#=5,
比赛2#=5#Cig2#=5,
比赛3#=5#Cig3#=5,
比赛4#=5#Cig4#=5,
比赛5#=5#Cig5#=5,
%挪威人(4)住在蓝河的旁边
[house(irish, green, jazz, embroidery, pizza), house(dutch, yellow, jpop, trainspotting, donuts), house(czech, purple, grunge, pachinko, beets), house(japanese, pink, country, gardening, pie), house(american, orange, hiphop, glassblowing, tofu)]
japanese