CS1950Y Lecture 6: Reachability
2/7/18
Reachability
Last class we did directed graphs.
sig City {
roads: City
}
one sig Pvd extends City {}
one sig Bos extends City {}
one sig Wor extends City {}
For this example, we will get one City named Pvd, one named Bos, and one named Wor, and maybe some unnamed cities too. If we look at an example, we will see that there can be self loops - you can leave a city and go right back to it! Let's write a predicate to prevent this:
pred noSelfLoopsA {
-- no Pvd->Pvd etc.
all c: City | c->c not in roads
all c: City | c not in c.roads
no c: City | c in c.roads
}
run noSelfLoopsA for 6
This says, for all cities in our world, there is no city where it has a relationship to itself in roads. All three of our lines mean exactly the same thing! We only need one, Tim wanted to show us how many different ways we could write this one idea.
Question: What is roads
?
Answer: roads
is a binary relation. Check it out in the evaluator!
Alloy has a few built in relations that are very helpful. For example, let's type in iden
in the evaluator. iden
is the relation from one thing to itself. iden & roads
will give us a set of all of the relations that are self loops. So if we write:
pred noSelfLoopsB {
no iden & roads
}
This should be equivalent to noSelfLoopsA. Question: What can we do in alloy to prove that noSelfLoopsA and noSelfLoopsB are equivalent?
Answer: We can use
iff
, if and only if, to check that these two are equivalent. To check that the two are equivalent using if and only if, we want to look for counterexamples, where noSelfLoopsA iff noSelfLoopsB
fails, like so:
assert SLSame {
noSelfLoopsA iff noSelfLoopsB
}
check SLSame for 10 City
Let's move on to another example! What can we write to ensure for a specific city, it has a road to Providence?
pred toPvd[c: City] {
--immediate edge from c to Pvd
c->Pvd in roads
--or we can write: Pvd in c.roads
}
run toPvd for 5
Initially, we tried some c: City | c->Pvd in roads
, but because we have our special predicate where we pass in a city (pred toPvd[c: City]
), we don't need some c: City
.
Question: Can you run
toPvd
without passing it a city?Answer: Yes! We can run
run toPvd for 5
, which is equivalent to run {some c: City | toPvd[c]}
We can also write this in another way:
pred toPvd2[c: City] {
c in roads.Pvd
}
Question: What is dot (.
) actually doing?Answer: If we look in the evaluator, we can do
roads.Pvd
and we get {Wor$0}
. Essentially what is happening here is we are looking at the relations in roads (think about each relation as two columns, ie. if we have a -> b, a is in column 1 and b is in column two), and we look at the second column of roads and compare it to Pvd. Then, once we find a match, we join, which effectively removes the matched columns, and returns us the first column of that relation.If we look at a more in depth example, say roads is made up of the following relations:
P -> B
B -> W
B -> P
W -> B
W -> P
If we do roads.P
, we see that we can join {B -> P}.P
and {W -> P}.P
. Joining {B -> P}.P
removes the two inner columns, which are P, and leaves us with B. Similarly, {W -> P}.P
leaves us with W. This means the result of roads.P
is {B, W}.What this is saying is which cities are the end of a left hand edge going to Providence. With dot join, we only look at the inner most columns, and we are left with the outer.
If instead we do roads.roads, it looks something like:
P -> B P -> B P -> P
B -> W B -> W P -> W
B -> P . B -> P = B -> B
W -> B W -> B B -> P
W -> P W -> P W -> W
W -> P
W -> B
Dot gives us bounded reachability.
Side note: In the evaluator, we saw an example that had Worcester, but it looked like
Wor ($toPvd2_c)
. Alloy is just letting us know here that Worcester is satisfying our toPvd2
predicate as our city c
.
Question: Is there some way to get alloy to give us unbounded reachability?
Amswer: We can use the
^
!
pred reachedPvd[c: City] {
Pvd in c.^roads
}
This gives us a city that can reach Pvd in any number of steps.