In our model, we constrain each course to have one instructor. This isn’t always true, but it’s a choice we’re making to simplify the model.
Does our model allow for two courses to have the same Course ID?
We looked at about 20 instances in Alloy, and none of them contained two courses with the same ID, but that doesn’t mean that there is no possible instance where there are two courses with the same ID.
To check this, we can use run {some disj c1, c2 : Course | c1.id = c2.id}
Not surprisingly, we find an instance satisfying this constraint (because we never specified that courses couldn’t have the same id)
Is that bad, though? We’re going to add state to our model so that we can add students and things like that. So having two courses with the same id might not be bad, because it could just be the same course at two different points in time.
Why can’t Alloy tell us how many instances there are?
It has to do a fully exhaustive search of the possible solution space and count them. This is a hard, time-consuming problem (at least exponential).
In the Visualizer, Alloy tells you the number of rows in each relation (the box on the side).
office
: type error because it doesn’t know if you mean the relation from Grad Student
to office
or Faculty
to office
Faculty <: office
gives us {Faculty$0 -> Room$1, ...}
Our model now allows one grad student to take, teach, and TA the same class.
How can we make our model allow for course changes?
We don’t want just one predicate like we had for Tic Tac Toe because there are many possible things that could happen, so our predicate would be really long and messy.
abstract sig Event {
pre, post : Course
}
sig AddStudent extends Event {
adds : Student,
addcid : CourseID
}
{
pre.instructor = post.instructor
pre.tas = post.tas
...
adds not in pre.roster
post.roster = pre.roster + adds
pre.id = addcid
}
This is called a sig fact, which is basically a fact that applies to every AddStudent Event
Is there a way to say “and everything else stays the same” (so that we don’t have to list out each field)? No, unfortunately we can't. This is actually a good thing, though, because it forces us to be specific about our constraints.
Now we want to show the progression of events on a course.
one sig Trace {
states: seq Course
}
fact AllCoursesUsed {
Course in Trace.states.elems -- all courses are part of the trace (just to simplify the instances)
}