CS195Y Lecture 5

2/3/17

Announcement: Alloy 1 goes out today (due 2/9)

How can we use alloy to determine whether the theory "if I am player X, go first and in the middle, I will always win." We ask it to find counterexamples. Add constraints that the first board has an 'X' in the middle, the last board has 'X' winning and no one had won before that.

Pitfalls with ordering: assumes the maximum number of atoms (a full game of 10 boards)

When unsatisfiable Alloy will try to give you a 'core' which is the minimum number of expressions causing the problem.

How does Alloy work? It will see how many atoms of each type it can create and then makes an example universe populated by those items. You're describing possible worlds and Alloy is trying to find examples of them. Every type has a set containing atoms of that type. Because we're working with sets we can reason about them using set relations. Field access 'dot' notation is essentially table access like in a database. It's a relational join. Move from thinking about Alloy with a 'object-orientated' schema to a relational one.

Evaluator: From the visualizer, you can use the Evaluator to look at relations in the given instance.
For example, in our Tic Tac Toe model, we can type “places” into the Evaluator, and it will show us the relation of all places in the current model. It has type Board -> Index -> Index -> Player because it includes all places, not for one particular board.
Note: in the visualizer, click Theme and then check the box that says Use original atom names. This will make the visualizer show the $0, $1, etc for each atom, which will be helpful when you are looking at the visualizer in combination with the Evaluator.

Dot operator:
Board$0.places will give us all of the places on Board$0
Board.places will give us all of the places on all of the boards
Board.places.X will give us all of the places where X has played on any board
Dot operator is similar to a join operation in databases
Join looks for equalities in the rightmost column of the first table and the leftmost column of the second table, and gives a relation for all of the rows that match.

Example:
|(One, Two, O)   | [X]
|(Three, One, X) |
--> [(Three, One)]

(Board.places.X).(Board.places.X)
Board.places.X has type Index -> Index so a dot join between them has the correct type.
Board.places.X = {One -> One, One -> Three, Three -> One, Two -> Three}
(Board.places.X).(Board.places.X) = {One -> One, One -> Three, One -> Two, Three -> One, Three -> Two, Two -> One}

Why is this useful?
This is really useful for graph relations, for example, finding reachability in a graph. Consider this example:

sig Node {
    edges : set Node
}
run { #Node = 3}

[N1] -> [N0] -> [N3] (N1 also has a self loop)
Note: = is used to show what the Evaluator evaluates to for each input
N = {N0, N1, N2}
edges = {N0->N2, N1->N0, N1->N1}
N.edges = {N0, N1, N2}
edges.N = {N0, N1}
edges.edges = {N1->N0, N1->N1, N1->N2} -- 2-hop paths 
edges - iden = {N0->N2, N1->N0} -- removes cycles
iden = {N0->N0, N1->N1, N2->N2} -- a relation from every atom to itself (built in)
(edges - iden).(edges - iden) = {N1->N2} -- 2-hop paths not including cycles
edges.(edges - iden) = {N1->N0, N1->N2} -- 2-hop paths not taking a self-loop for the second step
N.N = type error because it would result in a zero column table
edges.edges - iden = {N1->N0, N1->N2} -- 2-hop paths that do not start and end at the same place

How does iden know what type you want?
It doesn’t. iden includes every type in your model, which is okay if you’re doing something like set-difference, but it can sometimes get tricky because it can sometimes add things in that you aren’t expecting.
Can we construct the subset of iden including just the type we want?
Index.iden = {One, Three, Two} isn’t quite what we want, because it’s not a relation from each index to itself anymore
Index -> Index = {One->One, One->Two, One->Three, Two->One, Two->Two, Two->Three, Three->One, Three->Two, Three->Three}
Index->Index & iden = {One->One, Two->Two, Three->Three}
&: set intersection
+: set union
-: set difference
univ: set containing all atoms in your model
iden: relation from each atom to itself
~: switches the rows and columns in a two-column table

Limits of Alloy:
There are infinitely many possible directed acyclic graphs, so Alloy can’t possibly look at all of them. Instead, it looks at all possible graphs within some constraint like number of nodes or number of edges or something.
Alloy always implicitly limits bounds to 3 for each sig type. You can override this by saying run {} for 5, which will limit to 5 of each sig. This also applies to integers, so you can run into integer overflow problems