我尝试了使用合金进行建模的第一步,但遇到了一个无法解决的问题。我有以下规格:
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)写的《软件抽象》一书的示例。
它实质上是对具有(名称,地址)对的书籍进行建模。该添加谓词应获取一个Book实例b并通过向其添加(一个可能已经存在的)(名称,地址)对来从中创建另一个Book实例b'。
找到的前几个示例简单而令人信服,但单击“下一步”按钮,我将得到以下示例(上方为完整视图,下方为与书本的等效投影)
我看到两本书,第一本书Book0有两对(Name0,Addr2)和(Name1,Addr1)。从这些注释中,我们还可以看到add操作将添加新的二重奏(Name1,Addr2)。现在,当我看结果书Book1时, {(Name0,Addr0),(Name1,Addr2)}代替 {(Name0,Addr2),(Name1,Addr1),(Name1,Addr2)}
为什么将其视为法律实例?
(合金分析仪4.2,建立日期2012-09-25 15:54 EDT)
答案 0 :(得分:2)
这里有两件令人困惑的事情:
Book0
不参与该操作。相反,Book1
同时扮演b0
和b1
的角色。
在书中添加n->a
并不表示这是新地址。在这种情况下,Book1
在add
之前和之后都有此地址。
这是因为操作
b'.addr = b.addr + n->a
使用设置并集。细分为一个简单的示例:
{1, 2} = {1} + {2}
是真的。但是
{1, 2} = {1, 2} + {2}
也是如此。因此,在原始示例中,没有什么可以将n->a
排除在b.addr
之外。然后,合金分析器仅生成与给定约束一致的所有实例。
您可以通过在add
中添加一个断言来改进此示例:
b.addr[n] != a