As a homework, I have to define a heap data structure in Alloy.
I have come up with these rules
A node can have up to 1 father, left-son, right-son, left-brother and right-brother. It also has exactly 1 value and 1 level (as in how deep in the heap it is).
A node can have right-son if it has left-son.
A node cannot be in transitive closure over any of its relations (father, left-son, right-son, left-brother, right-brother).
The relations have to point to distinct nodes.
A node has a value and values must belong to a node.
A node's value must be less than the node's sons' values.
If a node has left-son and not left-brother, then the rightmost brother of its father has a right-son.
Node is its left-brother's right-brother and so on for all its relations.
Node's father's level is one less than node's level.
If there is a node with level two less, then all the nodes with that level must have both sons.
For any 2 nodes m, n that have the same level, m must be in transitive closure over left-brother of n, or in transitive closure over right-brother.
The question is twofold
A) I am not sure whether these rules are sufficient, or whether there is a better way to solve this altogether. (I think I could just resolve this all by having node consist of index and a value and transcribe heap-in-array algorithm into Alloy, but that seems rather inelegant.)
B) I have trouble implementing some of these rules.
I have implemented rules 1, 2, 3, 4, 5, 6, 7, 8 and 9. At least I think I did, and the generated graph does not contradict my expectations.
I do not know how to implement the last 2.
Also, the code I have so far:
open util/ordering [Key] as KO
open util/ordering [Level] as LO
sig Key{}
sig Level{}
sig Node {
key: one Key,
level: one Level,
father: lone Node,
left_brother: lone Node,
right_brother: lone Node,
left_son: lone Node,
right_son: lone Node
}
// There's exactly one root
fact {
one n : Node | n.father = none
}
// Every key has to belong to some node
fact {
all k : Key | some n:Node | n.key = k
}
fact {
all n : Node | (n.left_son != none && n.right_son != none) => #(KO/nexts[n.key] & (n.left_son.key + n.right_son.key)) = 2
}
// Son's father's son shall be Son etc
fact {
all n : Node | all m : Node | (n.left_son = m) => m.father = n
}
fact {
all n : Node | all m : Node | (n.right_son = m) => m.father = n
}
fact {
all n : Node | all m : Node | (m.father = n) => (n.left_son = m || n.right_son = m)
}
// Is this redundant?
fact {
all n : Node | all m : Node | (n.left_brother = m) => (m.right_brother = n)
}
fact {
all n : Node | all m : Node | (n.right_brother = m) => (m.left_brother = n)
}
// If a node has right-son, it must have a left-son.
fact {
all n : Node | (n.right_son != none) => (n.left_son != none)
}
// node having left son and left brother means that his left brother has a right son
fact {
all n: Node | (n.left_son != none && n.left_brother != none) => (n.left_brother.right_son != none)
}
// nodes father must be a level higher.
fact {
all n : Node | (n.father != none) => (LO/prev[n.level] = n.father.level)
}
// FIXME: this is wrong: There needs to be difference of 2 levels, not just a single level.
fact {
all n : Node | all m : Node | (LO/prevs[m.level] & n.level = n.level) => (n.left_son != none && n.right_son != none)
}
// TODO: If 2 nodes are in the same level, then they must be in left-brother* or right-brother* relation
// ????
// No node can be its own father
fact {
all n : Node | n.father != n
}
// No node can be in transitive closure over its ancestors
fact {
no n : Node | n in n.^father
}
// No node cannot be its own brother, son, etc...
fact {
all n: Node | n.left_brother != n
}
// Nor in its transitive closure
fact {
no n: Node | n in n.^left_brother
}
fact {
all n: Node | n.right_brother != n
}
fact {
no n: Node | n in n.^right_brother
}
fact {
all n: Node | n.left_brother != n
}
fact {
no n: Node | n in n.^left_brother
}
fact {
all n: Node | n.right_son != n
}
fact {
no n: Node | n in n.^right_son
}
fact {
all n: Node | n.left_son != n
}
fact {
no n: Node | n in n.^left_son
}
// All node relatives have to be distinct
fact {
all n: Node | n.left_son & n.right_son = none && n.left_brother & n.right_brother = none && (n.left_brother + n.right_brother) & (n.left_son + n.right_son) = none
&& (n.right_son + n.left_son + n.left_brother + n.right_brother) & n.father = none
}
run{}
For 10. something along the lines of
all m : Node | some father.father.m implies some m.left and m.right
would work, which is equivalent to
fact {
all m, n : Node | (n.father.father != none && n.father.father.level = m.level) => (m.left_son != none && m.right_son != none)
}
For 11., you can formulate it quite straightforwardly from the textual definition (of course, with using appropriate operators, namely for transitive closure).
As a general suggestion, try not to formulate such direct questions about homework problems (see this discussion). Since this answer comes pretty late, I think it's fine to try to give you some hints.
Related
I'm trying to define an Alloy Fact, in the below specification, which would prevent adding a Person to an Airplane's set of passengers, unless there's enough capacity. Furthermore, I would like to add another Fact, which would disallow the removal of a Person from an Airplane's passenger set, unless the latter's cardinality exceeded zero.
Any help would be much appreciated.
Cheers,
Phiroc
PS Here's my first stab at the initial Fact:
a'.onboard <= a'.capacity implies
no p and add [a,a',p] and del [a',a'',p] implies a.onboard = a''.onboard
... According to Daniel Jackson, it's invalid because the condition before the implied keyword could potentially be false. Furthermore, it doesn't have the expected effect of preventing the number of passengers from exceeding the airplane capacity, when running the model. For instance, you sometimes get sets with cardinality 4, although capacity is 2, when you execute the model...
sig Person {}
sig Airplane {onboard: set Person, capacity: Int}
fact {
some a,a': Airplane | disj [a.onboard, a'.onboard]
}
pred show(a: Airplane) {
#a.onboard > 0
a.capacity = 2
}
run show for 10 but 2 Airplane
pred add (a, a': Airplane, p: Person) {
a'.onboard = a.onboard + p
}
pred del (a, a': Airplane, p: Person) {
a'.onboard = a.onboard - p
}
assert delUndoesAdd {
all a,a',a'': Airplane, p: Person |
no p and add [a,a',p] and del [a',a'',p] implies a.onboard = a''.onboard
}
assert addIdempotence {
all a,a',a'': Airplane, p: Person |
add [a,a',p] and add [a',a'',p] implies a'.onboard = a''.onboard
}
check delUndoesAdd for 10 but 3 Airplane
check addIdempotence for 3
I think I've found a solution.
sig Person {}
sig Airplane {onboard: set Person, capacity: Int}
fact {
some a,a': Airplane | disj [a.onboard, a'.onboard]
}
fact {
all a: Airplane | a.capacity = 3 and #a.onboard <= a.capacity
}
pred show(a: Airplane) {
}
run show for 10 but 2 Airplane
pred add (a, a': Airplane, p: Person) {
a'.onboard = a.onboard + p
}
pred del (a, a': Airplane, p: Person) {
a'.onboard = a.onboard - p
}
assert delUndoesAdd {
all a,a',a'': Airplane, p: Person |
no p and add [a,a',p] and del [a',a'',p] implies a.onboard = a''.onboard
}
assert addIdempotence {
all a,a',a'': Airplane, p: Person |
add [a,a',p] and add [a',a'',p] implies a'.onboard = a''.onboard
}
check delUndoesAdd for 10 but 3 Airplane
check addIdempotence for 3
Some background: my project is to make a compiler that compiles from a c-like language to Alloy. The input language, that has c-like syntax, must support contracts. For now, I am trying to implement if statements that support pre and post condition statements, similar to the following:
int x=2
if_preCondition(x>0)
if(x == 2){
x = x + 1
}
if_postCondtion(x>0)
The problem is that I am a bit confused with the results of Alloy.
sig Number{
arg1: Int,
}
fun addOneConditional (x : Int) : Number{
{ v : Number |
v.arg1 = ((x = 2 ) => x.add[1] else x)
}
}
assert conditionalSome {
all n: Number| (n.arg1 = 2 ) => (some field: addOneConditional[n.arg1] | { field.arg1 = n.arg1.add[1] })
}
assert conditionalAll {
all n: Number| (n.arg1 = 2 ) => (all field: addOneConditional[n.arg1] | { field.arg1 = n.arg1.add[1] })
}
check conditionalSome
check conditionalAll
In the above example, conditionalAll does not generate any Counterexample. However, conditionalSomegenerates Counterexamples. If I understand all and some quantifiers correctly then there is a mistake. Because from mathematical logic we have Ɐx expr(x) => ∃x expr(x) ( i.e. If expression expr(x) is true for all values of x then there exist a single x for which expr(x) is true)
The first thing is that you need to model your pre-, post- and operations. Functions are terrible for that because they cannot not return something that indicates failure. You, therefore, need to model the operation as a predicate. The value of a predicate indicates if the pre/post are satisfied, the arguments and return values can be modeled as parameters.
This is as far as I can understand your operation:
pred add[ x : Int, x' : Int ] {
x > 0 -- pre condition
x = 2 =>
x'=x.plus[1]
else
x'=x
x' > 0 -- post condition
}
Alloy has no writable variables (Electrum has) so you need to model the before and after state with a prime (') character.
We can now use this predicate to calculate the set of solutions to your problem:
fun solutions : set Int {
{ x' : Int | some x : Int | add[ x,x' ] }
}
We create a set with integers for which we have a result. The prime character is nothing special in Alloy, it is only a convention for the post-state. I am abusing it slightly here.
This is more than enough Alloy source to make mistakes so let's test this.
run { some solutions }
If you run this then you'll see in the Txt view:
skolem $solutions={1, 3, 4, 5, 6, 7}
This is as expected. The add operation only works for positive numbers. Check. If the input is 2, the result is 3. Ergo, 2 can never be a solution. Check.
I admit, I am slight confused by what you're doing in your asserts. I've tried to replicate them faithfully, although I've removed unnecessary things, at least I think we're unnecessary. First your some case. Your code was doing an all but then selecting on 2. So removed the outer quantification and hardcoded 2.
check somen {
some x' : solutions | 2.plus[1] = x'
}
This indeed does not give us any counterexample. Since solutions was {1, 3, 4, 5, 6, 7}, 2+1=3 is in the set, i.e. the some condition is satisfied.
check alln {
all x' : solutions | 2.plus[1] = x'
}
However, not all solutions have 3 as the answer. If you check this, I get the following counter-example:
skolem $alln_x'={7}
skolem $solutions={1, 3, 4, 5, 6, 7}
Conclusion. Daniel Jackson advises not to learn Alloy with Ints. Looking at your Number class you took him literally: you still base your problem on Ints. What he meant is not use Int, don't hide them under the carpet in a field. I understand where Daniel is coming from but Ints are very attractive since we're so familiar with them. However, if you use Ints, let them at least use their full glory and don't hide them.
Hope this helps.
And the whole model:
pred add[ x : Int, x' : Int ] {
x > 0 -- pre condition
x = 2 =>
x'=x.plus[1]
else
x'=x
x' > 0 -- post condition
}
fun solutions : set Int { { x' : Int | some x : Int | add[ x,x' ] } }
run { some solutions }
check somen { some x' : solutions | x' = 3 }
check alln { all x' : solutions | x' = 3 }
[Update] I spent a lot of time studying #Hovercouch's fantastic solution (see his solution below). I took his solution, along with Peter Krien's insights and wrote up a summary: 3 ways to model the set of non-negative even numbers. I welcome your comments.
I am trying to create an Alloy model that defines a set of integers. I want to constrain the set to the integers 0, 2, 4, ...
I want to use a "generative" approach to defining the set:
0 is in the set.
If i is in the set, then i+2 is in the set.
Nothing else is in the set.
I am struggling with the last one - nothing else is in the set. How do I express that?
Below is the Alloy model that I created.
one sig PositiveEven {
elements: set Int
}
pred generate_set_members {
0 in PositiveEven.elements
all i: Int | i in PositiveEven.elements => i.plus[2] in PositiveEven.elements
// Nothing else is in the set - How to express this?
}
The simplest way to do this would be to create a relationship that maps each number N to N+2, and then take the reflexive-transitive closure of that relationship over 0.
one sig PositiveEven {
elements: set Int
}
one sig Generator {
rel: Int -> Int
} {
all i: Int | i.rel = i.next.next
}
pred generate_set_members {
PositiveEven.elements = 0.*(Generator.rel)
}
assert only_positive_elements {
generate_set_members =>
all i: Int | i in PositiveEven.elements <=> i >= 0 and i.rem[2] = 0
}
Note that you cannot use i.plus[2] instead of i.next.next, because Alloy integers overflow to negative.
What do you think of this:
let iset[min,max,step] = { i : Int |
i>= min
and i<max
and i.minus[min].div[step].mul[step]
= i.minus[min] }
pred show[ s : set Int ] {
iset[ 0, 10, 2 ] = s
}
run show for 0 but 8 int
The visualiser does not show the Int types so look in the Tree or Text view.
The following example shows two checks that appear equivalent, yet the second finds a counterexample while the first does not. When setting 'prevent overflow' to 'No', both return the same result:
sig A {
x : Int,
y : Int
}
pred f1[a:A] {
y = x ++ (a -> ((a.x).add[1]))
}
pred f2[a:A] {
a.y = (a.x).add[1]
y = x ++ (a -> a.y)
}
check {
all a : A | {
f1[a] => f2[a]
f2[a] => f1[a]
}
}
check {
all a:A | {
f1[a] <=> f2[a]
}
}
I am using Alloy 4.2_2015-02_22 on Ubuntu Linux with sat4j.
I am sorry not to be able to offer a more useful answer than the following. With luck, someone else will do better.
It is possible, I think, that your model exhibits a bug in Alloy. But perhaps instead the model exhibits a counter-intuitive consequence of the semantics of integers in Alloy when the Prevent Overflow flag is set. Those semantics are described in the paper Preventing arithmetic overflows in Alloy by Aleksandar Milicevic and Daniel Jackson. You may have an easier time following the details than I am having.
The following expressions seem to suggest (a) that the unintuitive results have to do with the fact that the law of excluded middle does not hold when negation is applied to undefined values, and (b) that in the case where a.x = 7 (or whatever the maximum value of Int is, in a particular scope), the predicates f1 and f2 behave differently:
pred xm1a[ a : A] { (f1[a] or not(f1[a])) }
pred xm2a[ a : A] { (f2[a] or not(f2[a])) }
pred xm1b[ a : A] { (not (f1[a] and not(f1[a]))) }
pred xm2b[ a : A] { (not (f2[a] and not(f2[a]))) }
// some sensible assertions: no counterexamples
check x1 { all a : A | a.x = 7 implies xm1a[a] }
check x2 { all a : A | a.x = 7 implies xm2a[a] }
check x3 { all a : A | a.x = 7 implies xm1b[a] }
check x4 { all a : A | a.x = 7 implies xm2b[a] }
// some odd assertions: counterexamples for y2 and y4
check y1 { all a : A | a.x = 7 implies not xm1a[a] }
check y2 { all a : A | a.x = 7 implies not xm2a[a] }
check y3 { all a : A | a.x = 7 implies not xm1b[a] }
check y4 { all a : A | a.x = 7 implies not xm2b[a] }
It's not clear (to me) whether the relevant difference between f1 and f2 is that f2 refers explicitly to a.y, or that f2 has two clauses with an implicit and between them.
If the arithmetic relation between a.x and a.y is important to the model, then figuring out exactly how overflow cases are handled will be essential. If all the matters is that a.x != a.y and y = x ++ (a -> a.y), then weakening the condition will have the nice side effect that the reader need not understand Alloy's overflow semantics. (I expect you realize that already; I mention it for the benefit of later readers.)
I am trying to use Spin Model Checker to modelcheck a Game between two objects (A and B). The objects move on a board, and each location is defined by its (x,y) coordinates. The two objects are supposed to not collide. I have three processes: init, A Model, B Model. I am model checking an ltl property: (liveness property to check if the two objects ever occupy same location)
ltl prop1 { [] (!(x_a == x_b) && !(y_a == y_b)) }
The error trail that I get is:
init -> A Model -> B Model -> init
However, I should not get an error trail (counterexample) based on the data that is shown: x_a=2, x_b=1, y_a=1, y_b=1.
Also the first init does go through all the lines of init process, but the second one only shows to the last line of it.
Also my A Model and B Model only consist of guards and actions in a 'do' block as shown below. However they are more complex and have if blocks on the right of '->'
active proctype AModel(){
do
:: someValue == 1 -> go North
:: someValue == 2 -> go South
:: someValue == 3 -> go East
:: someValue == 4 -> go West
:: else -> skip;
od
}
Do I need to put anything in an atomic block? The reason I am asking is that the line that the error trail is showing does not even go into the 'do' block, and it is just the first line of the two models.
EDIT:
The LTL property was wrong. I changed that to:
ltl prop1 { [] (!((x_a == x_b) && (y_a == y_b))) }
However, I am still getting the exact same error trail.
Your LTL property is wrongly implemented. Essentially, the counter example that SPIN found is a true counter example for the LTL as stated.
[] ( !(x_a == x_b) && !(y_z == y_b) ) =>
[] ( !(2 == 1) && !(1 == 1) ) =>
[] ( !0 && !1) =>
[] ( 1 && 0) =>
[] 0 =>
false
The LTL should be:
always not (same location) =>
[] (! ((x_a == x_b) && (y_a == y_b))) =>
[] (! ((2 == 1) && (1 == 1))) =>
[] (! (0 && 1) =>
[] (! 0) =>
[] 1 =>
true
Regarding your init and tasks. When starting your tasks you want to be sure that initialization is complete before the tasks run. I'll use one of two approaches:
init { ... atomic { run taskA(); run taskB() } where tasks are spawned once all initialization is complete`
or
bool init_complete = false;
init { ...; init_complete = true }
proctype taskA () { /* init local stuff */ ...; init-complete -> /* begin real works */ ... }
Your LTL may be failing during the initialization.
And based on your problem, if you ever change x or y you'd better change both at once in an atomic{}.