我得到了一个练习来使用我选择的约束求解器来解决斑马难题,我使用Prolog clpfd library进行了尝试。
我知道在 Prolog 中还有其他更惯用的方法来解决这个问题,但这个问题是专门关于clpfd
包的!
因此,我试图解决的难题的具体变体(鉴于其中有很多)是这个:
有五间房子
- 英国人住在红房子里
- 瑞典人养狗
- 丹麦人喜欢喝茶
- 绿房子留给白房子
- 温室的主人喝咖啡
- 抽 Pall Mall 的人拥有一只鸟
- 中间屋喝牛奶
- 黄房子的主人抽登喜路
- 挪威人住在第一所房子里
- 万宝路吸烟者住在猫主人旁边
- 马主住在抽登喜路的人旁边
- 温菲尔德吸烟者喜欢喝啤酒
- 挪威人住在蓝屋旁边
- 德国人抽罗斯曼烟
- 万宝路吸烟者有一个喝水的邻居
我试图用以下方法解决它:
房子可以拥有的每个属性都被建模为一个变量,例如“British”、“Dog”、“Green”等。属性可以取 1 到 5 的值,具体取决于它们所在的房子,例如,如果变量“狗”取值3,狗住在第三宫。
这种方法可以很容易地模拟这样的邻居约束:
def neighbor(X, Y) :-
(X #= Y-1) #\/ (X #= Y+1).
但不知何故,clpfd
即使(IMO)问题被正确建模(我使用与Choco 约束求解器完全相同的模型,结果是正确的),该包也没有产生解决方案。
这是完整的代码:
:- use_module(library(clpfd)).
neighbor(X, Y) :-
(X #= (Y - 1)) #\/ (X #= (Y + 1)).
solve([British, Swedish, Danish, Norwegian, German], Fish) :-
Nationalities = [British, Swedish, Danish, Norwegian, German],
Colors = [Red, Green, Blue, White, Yellow],
Beverages = [Tea, Coffee, Milk, Beer, Water],
Cigarettes = [PallMall, Marlboro, Dunhill, Winfield, Rothmanns],
Pets = [Dog, Bird, Cat, Horse, Fish],
all_different(Nationalities),
all_different(Colors),
all_different(Beverages),
all_different(Cigarettes),
all_different(Pets),
Nationalities ins 1..5,
Colors ins 1..5,
Beverages ins 1..5,
Cigarettes ins 1..5,
Pets ins 1..5,
British #= Red, % Hint 1
Swedish #= Dog, % Hint 2
Danish #= Tea, % Hint 3
Green #= White - 1 , % Hint 4
Green #= Coffee, % Hint 5,
PallMall #= Bird, % Hint 6
Milk #= 3, % Hint 7
Yellow #= Dunhill, % Hint 8,
Norwegian #= 1, % Hint 9
neighbor(Marlboro, Cat), % Hint 10
neighbor(Horse, Dunhill), % Hint 11
Winfield #= Beer, % Hint 12
neighbor(Norwegian, Blue), % Hint 13
German #= Rothmanns, % Hint 14,
neighbor(Marlboro, Water). % Hint 15
我是否误解了 中的概念clpfd
,或者我只是在这里遗漏了一些明显的东西?如果有帮助,您可以在这里找到使用 Choco 和 Scala 实现的相同方法。
编辑:我认为求解器无法解决问题的原因在于它从来没有为变量提供明确的值,而只是提供范围,例如“Fish 1..3\/5”。