Alloy在过河时的单对一量词

Alloy's lone vs one quantifier on river crossing

river crossing Alloy model中,这个谓词:

pred crossRiver [from, from', to, to': set Object] {
  one x: from | {
    from' = from - x - Farmer - from'.eats
    to' = to + x + Farmer
  }
}

模拟过河:from 一侧的物体 x 之一与农夫一起移动到 to 一侧。

为了测试我的理解,我将:one x: from改为lone x: from - Farmer---前者"exactly one thing"过河,后者"at most one non-Farmer thing"。

我认为后者更好地模拟了问题:农民在平等约束中被硬编码并且总是过河,lone 应该更好地传达农民可以带零或一件东西过河河流

然而,当运行修改模型后,结果是胡说八道:

这里的第二个状态实例显示了河两边的鸡和谷物,而农民根本没有过河。

我错过了什么? (这是 运行 在 Alloy 4.2_2015-02-22)

当您将 one 更改为 lone 时,您允许 Alloy 从 crossRiver 谓词简单地 return true,无论nearfar 是什么样子的。因此,对于该步骤,模型状态 不受 任何方式的约束。因此,Statenearfar 的每组可能值对于 Alloy.

都是完全可以的

这并不意味着 Alloy 会以某种方式优化它并且从不限制它。它将尝试 one(正确约束 nearfar)并且它只会 true 不约束解决方案。但是,两个解决方案都必须在解决方案space中。显然,还有更多不受约束的解决方案,因此您可能会看到垃圾。

如果使用one,那么Alloy必须满足谓词,也就是说body和farnear 关系的约束方式是在 State 中仅对有效交叉建模。

就把Alloy想象成石雕工具吧。你从一个巨大的状态块开始:nearfarState 中每个可以想到的原子组合都在那里。但是,如果您跳过跟踪中的约束,那么您只会得到原子的随机组合。

发生类似情况的常见问题是:

  some f : Foo | no f

这看起来总是错误的。 las,当没有 Foo 原子时,这是真的,因为 body 从未被查看过。