sig List {
header: set Node
}
sig Node {
link: set Node,
elem: set Int
}
我希望没有两个节点指向同一个元素。如何实现这一目标?
我真的不了解*运算符,但我尝试了
all n: Node | n.elem != n.*link.elem
假设n。* link.elem指向集合中的所有元素,例如
n.link.elem
n.link.link.elem
n.link.link.link.elem
但这不起作用。
答案 0 :(得分:3)
您可以在声明elem字段时简单地使用disj关键字
sig List {
header: set Node
}
sig Node {
link: set Node,
disj elem: set Int
}
这是表示没有两个节点n1和n2使得n1!= n2和n1.elem& n2.elem!=无
关于你的尝试,
all n: Node | n.elem != n.*link.elem
表示对于所有节点n,与n关联的元素与链接到n的节点关联的元素不同。 这有两个流程。
首先,您不会考虑未链接到n的节点。
其次,你应该考虑到elem是一组整数。 假设n1.elem = {1,2,3,4}和n2.elem = {1,2,3}。写入n1.elem是不够的{1,2,3,4}!= {1,2,3}。在这种情况下,n1和n2都指向1,2和3。因此,你需要脱节。
答案 1 :(得分:1)
为了更好地逼近整数结构链表,我建议使用以下模型。
sig List {
header: lone Node // empty list or one header node
}
sig Node {
link: lone Node, // 0 or 1 next node
elem: one Int // prohibit empty nodes
}
fact {
no n: Node | n in n.^link // prohibit cycles
all disj n, n': Node | n.elem != n'.elem // different nodes have different elements
all n: Node | one l: List | n = l.header or n in l.header.^link
// every node belongs to a list
}
答案 2 :(得分:1)
你需要节点吗?
这样抽象的东西怎么样?
abstract sig List {}
sig EmptyList extends List {}
sig NonEmptyList extends List {rest: List, contents: T}