CS195Y Lecture 11

2/17/2017

Modeling Dynamic Systems

Symmetry-breaking * Alloy tries to get rid of isomorphic instances * Can't catch them all (actually harder computationally than SAT)

Last time, things got interesting when we tried to define a CourseState. With CourseState.waitlist, we saw the seq keyword for the first time. Going back to the first week of class, we saw util/ordering and discussed its tradeoffs. With seq, we have another set of tradeoffs, and these two ways of ordering sets are appropriate for different situations.

Tim: What are some constraints to make sure the waitlist is actually a waitlist?

Student: There shouldn't be any intersection with the enrolled students.

We can use sig facts to more cleanly express facts about our sig. sig CourseState { ... } { no waitlist.elems & enrolled }

We didn't have to say someting like all cs : CourseState | <things with cs....>

Q: What is elems

Tim: You can think of it as a field that's defined for every sequence. It contains the set of elements of the sequence.

Q: Is it a relation?

Tim: It's a relation under the hood, but it's easier to think of as a field.

We can get an instance and see what's in these relations. run { some cs : CourseState | some cs.enrolled } for 4

Notice the skolemization $cs.

How many columns do we expect enrolled to have?

Student: 2, from CourseState to Student

How many columns should waitlist have? The leftmost column should be CourseList. When we show it in the evaluator, it has three columns: CourseState->Int->Student. Now, $cs.waitlist gives us a function from an index to a student.

Things we can do:

CourseState$0.waitlist.first to get the first element of the set

CourseState$0.waitlist[0] to also get the first element.

Q: Does it maintain uniqueness also? Can we get Student$0 at position 0 and 2?

Tim: When we use util/ordering, there are a couple constraints from it being a total ordering. We can't have duplicates and we force everything to exist. A sequence gives us something weaker, so we can have duplicates. It also doesn't have to contain everything. That means we can slice things off, like CourseState$0.waitlist.rest. We get more flexibility, but it comes with a performance hit.

Q: Can you intersect two sequences?

Tim: I can take their elems and intersect them, but it's not immediately clear how to preserve the ordering.

Sequences are not documented in the book. There's a reference page with everything you can do with them.

Now let's talk about changing the state, like enrolling in a course. We're going to use this transition predicate model.

``` pred enroll[pre : CourseState, s : Student, post : CourseState] { // We have a design choice about what to return for a student that's already enrolled. This one's sort of a // pre-condition, but the other constraints are more definitional. s not in pre.enrolled

// Conditions like this are called "framing conditions". If we don't specify, Alloy is free to give us instances
// where enrolling a student moves the course. In general, this is helpful because it helps us debug our intuition,
// but we really don't want it to here.
post.where = pre.where
// Thinking about the differences between Alloy and programming languages, could we write this as `pre.when = post.when`? Yes!
// `=` in Alloy is true equality, not assignment.
post.when = pre.when
pre.instructor = post.instructor
post.tas = pre.tas
post.id = pre.id

post.enrolled = pre.enrolled + s

// Alright, so what's up with the waitlist?

some pre.waitlist implies {
    // You can always group code into an implicit and with these curly braces.
    s = pre.waitlist.first
    post.waitlist = pre.waitlist.rest
}
no pre.waitlist implies {
    no post.waitlist
}
// With double implication like this, we have to make sure that our cases are mutually exclusive and exhaustive.

} ```

Q: Could you talk a little bit about the difference between brackets and parens?

Tim: It used to be that you could use brackets and parens interchangeably. They changed it so you have to use brackets in certain situations, and now I use parens only for grouping.

Q: Is this student enrolling from the waitlist or are they an arbitrary student?

Tim: Both! We're going to bake in support for both cases and branch the predicate. If the student's on the waitlist, there are some side effects that should happen.

Q: Without a cap, how do you know if someone needs to be put on the waitlist?

Tim: For now, we're going to completely sidestep that question! In modeler speak, we're going to abstract that out. It might come back and cause trouble later.

Q: What if you enroll a TA?

Tim: What should happen? Have you been in a class with an MTA enrolled? Or with a grad TA?

Q: Are you talking about a TA in general or a TA for the course?

Tim: I'm actually talking about this course. In the past, this very class has had (grad) TAs enrolled as students. For now, we won't specify what should happen and we'll wait to see the actual instances.

Q: Could you say pre.enrolled = post.enrolled - s?

Tim: I think the answer is yes, and we could give it a test, but I'm worried about time.

Q: If you have a really big sig, is there a way to say that all but a few properties should be the same?

Tim: Unfortunately, Alloy doesn't have a way to specify "all else being equal".

Q: Couldn't you say that pre.waitlist is a subset of post.waitlist?

Tim: You could - there are a couple ways of getting at this. I like to put it as, "in this case, this happens".