Reputation: 151
sig List {
header: set Node
}
sig Node {
link: set Node,
elem: set Int
}
I want no two nodes to point to the same element. How can this be achieved?
I don't really understand the * operator, but I tried
all n: Node | n.elem != n.*link.elem
assuming that n.*link.elem would point to all elements in the set, such as
n.link.elem
n.link.link.elem
n.link.link.link.elem
But this is not working.
Upvotes: 0
Views: 267
Reputation: 2768
Do you need nodes?
How about something more abstract like this?
abstract sig List {}
sig EmptyList extends List {}
sig NonEmptyList extends List {rest: List, contents: T}
Upvotes: 1
Reputation: 1021
For a better approximation of the linked list of integers structure, I'd suggest the following model.
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
}
Upvotes: 1
Reputation: 4171
you can simply use the disj keyword when declaring your elem field
sig List {
header: set Node
}
sig Node {
link: set Node,
disj elem: set Int
}
This is a shorthand to express that there's no two nodes n1 and n2 such that n1 != n2 and n1.elem & n2.elem != none
Concerning what you tried,
all n: Node | n.elem != n.*link.elem
says that for all node n, the elements associated to n is different from the elements associated to the nodes linked to n. This has two flows.
First, you do not take into considerations nodes that are not linked to n.
Second, you should take into account that elem is a set of Integers. Suppose n1.elem= {1,2,3,4} and n2.elem={1,2,3}. writting n1.elem is not enough as {1,2,3,4} != {1,2,3}.In this case, n1 and n2 points both to 1,2 and 3 . A disjunction is thus what you need.
Upvotes: 3