CS195Y Lecture 12

2/22/2017


Back to our Courses model. Now we want to model how we can enroll students into our course

 fact  firstState {
    no first.enrolled
    no first.waitlist.elems
}

fact nextState {
    all s : State - last | {
        some st : Student | enroll[s, st, s.next]
    }
}

This seems to work for enrollment, but what about the other actions a we might want to do? What about adding an instructor? Generally, we can write a predicate for every action we might want to do and then we can add these to a giant OR inside our nextState fact.

fact  firstState {
    no first.enrolled
    no first.waitlist.elems
}

fact nextState {
    all s : CourseState - last | {
        -- enroll a student
        some st : Student | enroll[s, st, s.next]
        or
        -- change an instructor
        some inst : Faculty | setInstructor[s, inst, s.next]
        or
        ...
    }
}

But before we go hog-wild making new predicates, let's make sure our model actually works the way we think it does. It's looking good!

Moving on!

But first, some terminology.
What Alloy really does is perform a search. The other tools we'll use do similar things.
Two things we might want to talk about are soundness and completenes. Is Alloy sound or complete? If Alloy were unsound, it would show instances that don't make the specification. Alloy better be sound! If alloy were incompletete, it wouldn't show us every instance that statisfies the spec. Alloy is complete up to the bounds you are using to search.

Underconstraint: Some "incorrect" instances. Your spec is underconstrained becuase the instances doesn't conform to your intuition.
Overconstraint: Some "missing" instances. Your spec is overconstrained because some of the instances you expect won't be there.

Are these mutually exclusive? Not necessarily, you could have overconstrained to less than 3 nodes and underconstrained acyclicity.
Could we under and over constrain the same constraint? No, not really.

Ultimate overconstaint: Any instance that is unsatisifiable. You can only use the UnSat core when your overconstraint makes the spec unsat. What should you do to figure it out if it's sat? One Way: Take away most of the constraints and try them in the evaluator
What if we wanted to try something else?

We're looking at an undirected tree spec but it only produces trees with a single node and no edges. Why could that be? How can we figure it out? Let's try with the evaluator.

Note this is an experimental feature! But we can ask Alloy in the evaluator why we cannot hae 2 nodes and it tries to explain why! Let's change our spec to the correct one. Let's see if we can find some self loops after we comment out that constraint. But there aren't any? Let's ask Alloy why not!
But of course! It's the undirected tree acyclic part. This pred does not protect self loops.

You can try out this experimental feature on your homework if you'd like!