简体   繁体   English

爱因斯坦谜题的合金模型

[英]Alloy model of the Einstein puzzle

[ Update ] Thanks to the excellent insights by @Daniel Jackson and @Peter Kriens I fixed my Alloy model. [更新] 感谢@Daniel Jackson 和@Peter Kriens 的出色见解,我修复了我的合金模型。 Now the Alloy Analyzer generates one instance.现在 Alloy Analyzer 生成一个实例。 I wrote up this problem and I show the solution.我写了这个问题并展示了解决方案。 I show for each of the 5 houses the color, nationality, drink, cigarette, and pet.我为 5 个房子中的每一个显示颜色、国籍、饮料、香烟和宠物。 By the way, it is the German who keeps fish.顺便说一下,养鱼的是德国人。 Here is my write-up.是我写的。

I created an Alloy model of the Einstein puzzle.我创建了爱因斯坦谜题的合金模型。 See below.见下文。 When I ran my model, the Alloy Analyzer found several instances.当我运行我的模型时,Alloy Analyzer 发现了几个实例。 I thought there would be only one instance (one solution).我以为只有一个实例(一种解决方案)。 This makes me wonder if my model is correct.这让我怀疑我的模型是否正确。 Do you see a problem with my model?你看到我的模型有问题吗? Should there be only one solution to the Einstein puzzle?爱因斯坦难题应该只有一种解决方案吗?

Here is the Einstein puzzle:这是爱因斯坦的谜题:

There are five houses of different colors next to each other on the same road.在同一条路上,有五栋不同颜色的房子紧挨着。 In each house lives a man of a different nationality.每个房子里住着一个不同国籍的人。 Every man has his favorite drink, his favorite brand of cigarettes, and keeps pets of a particular kind.每个男人都有他最喜欢的饮料,他最喜欢的香烟品牌,并养着一种特殊的宠物。 Here are the constraints:以下是限制条件:

1.  The Englishman lives in the red house.
2.  The Swede keeps dogs.
3.  The Dane drinks tea.
4.  The green house is just to the left of the white one.
5.  The owner of the green house drinks coffee.
6.  The Pall Mall smoker keeps birds.
7.  The owner of the yellow house smokes Dunhills.
8.  The man in the center house drinks milk.
9.  The Norwegian lives in the first house.
10. The Blend smoker has a neighbor who keeps cats.
11. The man who smokes Blue Masters drinks beer.
12. The man who keeps horses lives next to the Dunhill smoker.
13. The German smokes Prince.
14. The Norwegian lives next to the blue house.
15. The Blend smoker has a neighbor who drinks water.

The question to be answered is: Who keeps fish?要回答的问题是:谁养鱼?

Here is my Alloy model:这是我的合金模型:

open util/ordering[House]

sig House {
    color: Color,
    nationality: Nationality,
    drink: Drink,
    cigarette: Cigarette,
    pet: Pet
}

abstract sig Color {}
one sig red extends Color {}
one sig green extends Color {}
one sig yellow extends Color {}
one sig blue extends Color {}
one sig white extends Color {}

abstract sig Nationality {}
one sig Englishman extends Nationality {}
one sig Swede extends Nationality {}
one sig Dane extends Nationality {}
one sig German extends Nationality {}
one sig Norwegian extends Nationality {}

abstract sig Drink {}
one sig tea extends Drink {}
one sig coffee extends Drink {}
one sig milk extends Drink {}
one sig beer extends Drink {}
one sig water extends Drink {}

abstract sig Cigarette {}
one sig Pall_Mall extends Cigarette {}
one sig Dunhills extends Cigarette {}
one sig Blend extends Cigarette {}
one sig Blue_Masters extends Cigarette {}
one sig Prince extends Cigarette {}

abstract sig Pet {}
one sig dog extends Pet {}
one sig bird extends Pet {}
one sig horse extends Pet {}
one sig cat extends Pet {}
one sig fish extends Pet {}

fact {
    some disj h1, h2, h3, h4, h5: House | h1.color = red and h2.color = green and h3.color = yellow and h4.color = blue and h5.color = white
    no disj h,h': House | h.nationality = h'.nationality
    some h: House | (h.nationality = Englishman) and (h.color = red)
    some h: House | (h.nationality = Swede) and (h.pet = dog)
    some disj h, h': House | (h.color = green) and (h'.color = white) and (h'.prev = h)
    some h: House | (h.color = green) and (h.drink = coffee)
    some h: House | (h.cigarette = Pall_Mall) and (h.pet = bird)
    some h: House | (h.color = yellow) and (h.cigarette = Dunhills)
    some h: House | (some h.prev.prev) and (some h.next.next) and (h.drink = milk)
    some h: House | (h = first) and (h.nationality = Norwegian)
    some h: House | (h.cigarette = Blue_Masters) and (h.drink = beer)
    some disj h,h': House | (h.pet = horse) and (h'.cigarette = Dunhills) and ((h.next = h') or (h.prev = h'))
    some h: House | (h.nationality = German) and (h.cigarette = Prince)
    some disj h,h': House | (h.nationality = Norwegian) and (h'.color= blue) and (h.next = h')
    some disj h,h': House | (h.cigarette = Blend) and (h'.drink = water) and (h.next = h')
}

pred Who_keeps_fish {
    some h: House | h.pet = fish
}

run Who_keeps_fish for 5

The puzzle is supposed to have a unique solution.这个谜题应该有一个独特的解决方案。 I would not be surprised to find multiple instances, though, due to incomplete symmetry breaking.不过,由于不完全对称破坏,我不会对发现多个实例感到惊讶。 What is more surprising (and suggests to me a problem with your model) is that the first instance generated has both the Norwegian and the German keeping fish.更令人惊讶的是(并向我表明您的模型存在问题)是生成的第一个实例同时包含挪威和德国饲养的鱼。 Looks as if you need to add the constraint that the occupants of the houses keep different pets (ie, the pet relation is injective).看起来好像您需要添加房屋的居住者饲养不同宠物的约束(即,宠物关系是单射的)。

I think the text of your code deviates too much from the original definition.我认为您的代码文本与原始定义偏差太大。 In my experience when you have to follow an existing spec it is crucial to express the text as literal as possible in Alloy.根据我的经验,当您必须遵循现有规范时,在 Alloy 中尽可能字面地表达文本至关重要。 Ie you fit the model so that the vocabulary matches the original spec (puzzle).即您拟合模型,以便词汇与原始规范(拼图)相匹配。

In this case the house seems to be the central point of reasoning.在这种情况下,房子似乎是推理的中心点。 So I created a House atom that holds the different properties.所以我创建了一个拥有不同属性的 House 原子。 I named the fields so they match the words in the descriptions.我为这些字段命名,使它们与描述中的单词相匹配。 I then used the ~ to get the proper word order.然后我使用 ~ 来获得正确的词序。 Ie 'the Englishman lives' becomes 'Englishman.~lives' or 'lives.Englishman'.即“英国人生活”变成“英国人。〜生活”或“生活。英国人”。 I find this strategy quite crucial to work with Alloy (or any formal language).我发现这个策略对于使用 Alloy(或任何正式语言)非常重要。 The onus to verify should be on the underlying model not on my brain trying to interpret math symbols.验证的责任应该在底层模型上,而不是在我试图解释数学符号的大脑上。 I think this is a similar approach as creating a DSL.我认为这与创建 DSL 的方法类似。

I then got one solution with the following model:然后我得到了一个具有以下模型的解决方案:

open util/ordering[House]

enum Color { red, green, yellow, blue, white}
enum Nationality { Englishman, Swede, Dane, German, Norwegian}
enum Drink { tea, coffee, milk, beer, water}
enum Cigarette {Pall_Mall, Dunhills, Blend, Blue_Masters, Prince}
enum Pet { dogs, birds, horses, cats, fish }

sig House {
    colored  : disj Color,
    lives    : disj Nationality,
    drinks   : disj Drink,
    smoker   : disj Cigarette,
    keeps    : disj Pet
} 

pred House.hasNeighbourWho[ other : House ] { 
    other in this.(prev+next) 
}

let centerHouse = first.next.next

fact {
    // 1.  The Englishman lives in the red house.
    Englishman.~lives in colored.red

    // 2.  The Swede keeps dogs.
    Swede.~lives in keeps.dogs

    // 3.  The Dane drinks tea.
    Dane.~lives in drinks.tea

    // 4.  The green house is just to the left of the white one.
    green.~colored = colored.white.prev

    // 5.  The owner of the green house drinks coffee.
    green.~colored = drinks.coffee

    // 6.  The Pall Mall smoker keeps birds.
    Pall_Mall.~smoker = keeps.birds

    // 7.  The owner of the yellow house smokes Dunhills.
    yellow.~colored = smoker.Dunhills

    // 8.  The man in the center house drinks milk.
    centerHouse = drinks.milk

    // 9.  The Norwegian lives in the first house.
    Norwegian.~lives  = first

    // 10. The Blend smoker has a neighbor who keeps cats.
    Blend.~smoker.hasNeighbourWho[ keeps.cats ] 

    // 11. The man who smokes Blue Masters drinks beer.
    Blue_Masters.~smoker = drinks.beer

    // 12. The man who keeps horses lives next to the Dunhill smoker.
    keeps.horses.hasNeighbourWho[smoker.Dunhills]

    // 13. The German smokes Prince.
    German.~lives = smoker.Prince

    // 14. The Norwegian lives next to the blue house.
    Norwegian.~lives.hasNeighbourWho[colored.blue]

    // 15. The Blend smoker has a neighbor who drinks water.
    Blend.~smoker.hasNeighbourWho[drinks.water]
}
pred solution[ p : House ] {
     p = keeps.fish
}
run solution for 5 but exactly 5 House

Updated Removed meta stuff and used disj instead更新删除元数据并使用disj代替

The original solution seems to miss the constraints that no owners have the same pet, cigarette and drink.最初的解决方案似乎忽略了没有主人拥有相同的宠物、香烟和饮料的限制。

    no disj h,h': House | h.pet = h'.pet // otherwise there are solutions with green and white house having both dog as pet
    no disj h,h': House | h.cigarette = h'.cigarette // not really required
    no disj h,h': House | h.drink = h'.drink // not really required

Without these, as noted above, you get illegal solutions.没有这些,如上所述,您将获得非法解决方案。 Here is a rendering constructed with ProB showing an illegal solution这是使用 ProB 构建的渲染图,显示了非法解决方案

After correction, you get this solution with ProB (using Alloy2B and VisB : (see here if you are interested in the visualization)更正后,您将使用 ProB 获得此解决方案(使用 Alloy2B 和 VisB :(如果您对可视化感兴趣,请参阅此处

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM