您的方法有点令人困惑,它可能会简单得多。我会这样做
sig Node{
next : lone Node
}
one sig Head in Node {} -- head node is still a node
fact{
all n : Node | n not in n.^next -- no cycles
no next.Head -- no node points to Head
all n : Node - Head | some next.n -- for all other nodes, there has to be someone pointing to them
}
run {} for 10
该模型是静态的,为了使模型动态,您需要了解状态的概念。我建议您阅读由 Alloy 的作者撰写的Software Abstractions 。链表的动态方法对您来说太复杂了,此时您无法理解,您应该做一些更简单的练习。
状态的基本思想是(根据书中的通讯录例子练习):
静态示例:
sig State {}
abstract sig Target {}
sig Email extends Target {}
abstract sig Name extends Email {
name : set State,
addr : Target some -> State
}
sig Group, Alias extends Name {}
fact {
all a : Alias | lone a.addr
no n : Name | n in n.^addr
}
run {}
动态的例子,在局部状态成语中(=表达状态的一种方式,还有一个全局状态成语和一个事件成语)。看看谓词
open util/ordering[State]
sig State {}
abstract sig Target {}
sig Email extends Target {}
abstract sig Name extends Email {
name : set State,
addr : Target -> State
}
sig Group, Alias extends Name {}
fact {
all s : State {
all a : Alias & name.s | lone a.addr.s
no n : name.s | n in n.^(addr.s)
addr.s in name.s -> Target
addr.s :> Name in Name -> name.s
}
}
run {} for 3 but exactly 1 State
-- adding a name n, for a given pre state s and post state s'
pred addName [n : Name, s,s' : State] {
-- the name must not exist in the pre state
n not in name.s
-- the relation names in the post state is what is was
-- in the pre state in addition to the new name
name.s' = name.s + n
-- the address relation stays the same
addr.s' = addr.s
}
run addName for 3 but 2 State
pred addTarget [n : Name, t : Target, s,s' : State] {
t not in n.addr.s
name.s' = name.s
addr.s' = addr.s + n->t
}
run addTarget for 3 but 2 State
您还可以查看以下幻灯片。