发现 Alloy 规格的意外实例

Unexpected Instance found for Alloy specification

我尝试使用 Alloy 进行建模,但遇到了一个我无法理解的问题。我有以下规格:

module tour/AddressBook1

sig Name, Addr{}
sig Book {
    addr: Name->lone Addr
}

// operation: adds a (name, address) to the Book b, resulting in b'
pred add (b, b' : Book, n:Name, a:Addr) {
    b'.addr = b.addr + n->a
}

run add for 3 but 2 Book

到目前为止没有什么特别的。它实际上是 Daniel Jackson 的书 'Software abstraction' 中的示例。

它本质上是对书籍进行建模,这些书籍具有与之关联的(名称,地址)对。 add-predicate 应该获取 Book-instance b 并通过向其添加(可能已经存在的)(name,address)-pair 来从中创建另一个 Book-instance b'。

找到的前几个示例简单且令人信服,但单击“下一步”按钮我最终得到以下示例(上面的完整视图,下方书籍的等效投影)

我看到两本书,起始书 Book0 有两对 (Name0, Addr2) 和 (Name1, Addr1)。从注释中我们还可以看到添加操作将添加新的 duo (Name1, Addr2)。当我现在查看结果书 Book1 时 {(Name0, Addr0),(Name1, Addr2)} 而不是 {(Name0, Addr2),(Name1, Addr1),(Name1, Addr2)}

为什么这被认为是合法实例?

(Alloy Analyzer 4.2,构建日期 2012-09-25 15:54 美国东部时间)

这里有两个令人困惑的地方:

  1. Book0不参与运算。相反 Book1 具有 b0b1 的作用。

  2. n->a 添加到一本书中并不能断言这是一个新地址。在这个例子中,Book1add 之前和之后都有这个地址。 这是因为操作

    b'.addr = b.addr + n->a
    

    使用设置联合。分解为一个更简单的例子:

    {1, 2} = {1} + {2}
    

    是真的。但是

    {1, 2} = {1, 2} + {2}
    

    也是如此。所以在最初的例子中,没有什么可以排除 n->a 已经成为 b.addr 的一部分。而 Alloy 分析器只是生成所有符合给定约束条件的实例。

您可以通过在 add 中添加断言来改进此示例:

    b.addr[n] != a