Why does NoRoomConflicts generate a binary relation while NoRoomConflicts_alt "works" - alloy

Consider the Alloy model below, a stripped-to-the-essence version of a student submission. The problem is a course scheduling system, and the student was trying to say there are no conflicts (two distinct courses meeting in the same place at the same time):
abstract sig Room{}
one sig S20, S30, S50 extends Room{}
abstract sig Period{}
one sig Mon, Tue, Wed, Thu, Fri extends Period{}
// Courses and the room and periods when they meet.
some sig Course {
where : Room,
when : some Period
}
// No two Courses with any common meeting Periods can be
// in the same Room - from the student.
pred NoRoomConflicts_student {
no c : Course | no d : Course |
c != d && some c.when & d.when && d.where = c.where
}
run NoRoomConflicts_student
// No two Courses with any common meeting Periods can be
// in the same Room - my recasting.
pred NoRoomConflicts_alt {
no c : Course, d : Course |
c != d && some c.when & d.when && d.where = c.where
}
run NoRoomConflicts_alt
When NoRoomConflicts_alt is run we get solutions that conform to the spec.
But when NoRoomConflicts_student is run, suddenly "d" becomes a binary relation between Courses and the solutions show conflicts.
(a) Why was "d" transformed in this way?
(b) Given (a), shouldn't c != d raise a type error?
Note: I'm not claiming that the two predicates are equivalent (my head aches trying to do the double negation) - I just want to know how "d" suddenly becomes a binary relation when NoRoomConflicts is run.
Version: Alloy Analyzer 4.2_2015-02-22 (build date: 2015-02-22 18:21 EST)

First, what you're seeing in the solution is that certain quantified variables (d in this case) get skolemized so that you can see their values. If you're solving a constraint of the form (all x | some y | ...), the skolemized value of y will have to be a relation -- giving a y value for each x. This is not the actual type of the Alloy variable, which is why there is no type error. For a full explanation, see Section 5.2.2 of my book (Software Abstractions).
Second, the two formulas are not the same. This is explained on page 293 of my book. In short, it's because "no c, d | P" means you can't find a c and d such that P, and "no c | no d | P" means you can't find a c such that you can't find a d such that P.

Related

UML class diagram association properties {subsets < Association end > } | {union} | {redefines}

I don't quite understand what {subset} stands for when it comes to the association between class diagrams in UML. I've found this PDF that talks about it on page 4: https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.138.5537&rep=rep1&type=pdf.
Here is the diagram & text that you can also find on page 4:
I read this and I'm not 100% about what {subsets < class > } is about.
It says that "The slot representing d will be a subset of the slot representing b. Elements of type B can be inserted into slot b and elements of type D can be inserted into slots b and d."
So, is {subset} some kind of polymorphism ? I think that thorugh "slot" they mean like the argument of a method that is of type B. And because D subsets b that means that D is like the sub-class of b so it can be passed down as "b" in arguments because of Polymorphism.
So the question is :
What is {subsets < class > } exactly, is it representing a sub class ?
On top of that I have other questions:
What are {union}, {redefines < class > }, {nonunique} & {sequence}. What do does stand for ?
Some examples in code would make it easier to understand.
So the question is : What is {subsets < class > } exactly, is it representing a sub class ?
It is not {subsets < class >} but {subsets < property name >}
In the given diagram D is the only visible class specializing B, and if they are no other classes specializing B then all the instances of B are instances of D and then {subset b} is equal to b.
But having at least :
all the instances of B are not necessary instances of D (including of classes specializing D), this is why d only concerns a subset of the instances of B concerned by b.
In your diagram and mine the subsets are not really useful, but there are for instance in case of redefinition e.g. {subsets a, redefines a} {subsets b, redefines b}
What are {union}, {redefines < class > }, {nonunique} & {sequence}
referring to formal/2017-12-05 ยง9.5.4 page 113 and 114 :
union means that the property is a derived union of its subsets.
nonunique: means that there may be duplicates in a multi-valued property. This is the opposite of unique meaning there is no possible duplicates. For instance supposing b is {nonunique} then some instances of B can be present several times in b. If the property is implemented in C++ by a std::set it is {unique}.
sequence means that the property represents an ordered bag, this is a shortcut of {nonunique, ordered}. This is the case of std::vector and std::list in C++.
{redefines < property-name > } (not {redefines < class >}) means that the property redefines an inherited property identified by < property-name >. If in your diagram the {subsets b} is replaced by {redefines b} then the classes C only has the slot (e.g. attribute in C++ etc) d. This is not like having b private so not accessible from C, that really means d is a redefinition of b.

Ordering in Alloy using util/ordering

I am trying to learn about how ordering works in Alloy. I have a time signature which I have used to instantiate the ordering module. I want the predicate addPage to add a page to the book at time t' where t' = t.next. (Basically add a page to the Book on the next time) However it is not working as expected and instead Time2 has lesser number of pages than Time1. Can someone explain to me why this is happening? Thanks.
open util/ordering[Page] as P0
open util/ordering[Time] as T0
sig Page {}
sig Time {}
sig Book
{
pages: Page -> Time
}
pred addPage(b:Book, p:Page, t: Time)
{
t != T0/last implies
{
let t' = t.next |
b.pages.t' = b.pages.t + p
}
}
run addPage {} for 3
The problem are the extra curly braces in the run statement.
I think Alloy executes an empty predicate in this case.
Try:
run addPage for 3
instead. You will see a visualization where the selected instances for b, t and p are marked.
You're trying to change state which can only be simulated in constraint logic.
Please notice that the expression in addPage is basically ineffective /run your model without it/ and that there's only one Book atom in the solution.
Here's a model you can start with and gradually refine.
open util/ordering[Time]
sig Page {}
sig Time {}
sig Book {
pages : Page lone -> Time // each Time atom is mapped to at most one Page atom
}
pred addPage(b0, b1 : Book, pg : Page, t0, t1 : Time) {
one pg and // one page at a time (it's likely redundant)
not pg in b0.pages.Time and // it's a 'new' page
b0.pages + pg->t1 = b1.pages and // 'new state' of b0
t1 = t0.next // pg is 'added' with the next time stamp
}
run addPage for 3 but 2 Book
I used the optional 'and' operators, placed t1 = t0.next at the end of the constraint, positioned b1.pages /representing the 'new state'/ on the right and used quotes in the comments to emphasize that there's no real state change and sequence of operation in the sense imperative programming works.

How to interpret an Alloy fact

I am reading an article that uses Alloy to model some safety and security requirements for aircraft avionics. I am struggling to understand one of the "fact constraints" shown in the article.
Data flows into systems. Data is consumed by the systems. The model declares a set of Data, a set of System, and a consumedBy relation (Data is consumed by System):
sig Data {
consumedBy: some System
}
sig System {}
The model then declares a set of "criticality values." A relation maps criticality to data. Another relation maps criticality to system:
sig Criticality {
concernedData: one Data,
concernedSystem: one System
}
Next, the model expresses two facts. It's the second fact that I am struggling with.
The first fact says that each system consumes at least one datum:
all s: System | some consumedBy.s
The article has this comment about the second fact:
// for any system which consumes a given datum,
// the said datum and system should belong to
// a same unique criticality
I think the comment is saying this: If a system consumes a datum, then the datum and the system must have the same criticality. For example, if datum D1 is consumed by system S1 and datum D1 has criticality C1, then system S1 must also have criticality C1. Do you agree with that interpretation of the comment?
Now, here is how the fact is expressed in Alloy:
all d: Data | all s: System | one c: Criticality |
c.concernedData = d and c.concernedSystem = s
My understanding of how to read that fact is this:
The following constraint holds for exactly one c in Criticality:
For every d in Data and every s in System:
c.concernedData = d and c.concernedSystem = s
Is that a correct understanding of the fact? If so, I don't think the fact is expressing the same thing as the description in the comment.
So my questions are these:
One: the comment says this:
// for any system which consumes a given datum,
// the said datum and system should belong to
// a same unique criticality
Does the following Alloy fact express the same thing as the comment?
all d: Data | all s: System | one c: Criticality |
c.concernedData = d and c.concernedSystem = s
Two: if the comment and the Alloy fact are not the same, then what is the correct way to express the comment in Alloy?
Here is an Alloy model that compares the paper's version of the fact to what I believe captures what you want to express:
sig Data {consumedBy: some System}
sig Criticality {
concernedData: one Data,
concernedSystem: one System
}
sig System {}
// the paper's statement:
// for any system which consumes a given datum,
// there is one criticality that has that data and system
// as its concernedData and concernedSystem
pred Paper {
all d: Data | all s: d.consumedBy | one c: Criticality |
c.concernedData = d and c.concernedSystem = s
}
// your interpretation:
// If a system consumes a datum, then the datum and the system
// must have the same (single) criticality
pred You {
all d: Data | all s: d.consumedBy |
concernedData.d = concernedSystem.s and one concernedSystem.s
}
check {Paper implies You} for 2
If you execute this, you get the following counterexample that shows the difference between the two:
In short, the paper version says there is only one criticality shared by both; your version says that the datum and system are each associated with one criticality, and it's the same one (which is stronger).
I don't know which is right in this case.
The "one" quantifier, while having a very simple semantics ("one x: S | P" means P is true for one x in the set S) can be confusing because of how we're tempted to read quantifiers in natural language. There's a half page discussion of an example of this in the FAQ of Chapter 3 of Software Abstractions, on p.73.

Unexpected results in playing with relations

/*
sig a {
}
sig b {
}
*/
pred rel_test(r : univ -> univ) {
# r = 1
}
run {
some r : univ -> univ {
rel_test [r]
}
} for 2
Running this small test, $r contains one element in every generated instance. When sig a and sig b are uncommented, however, the first instance is this:
In my explanation, $r has 9 tuples here and still, the predicate which asks for a one tuple relation succeeds. Where am I wrong?
An auxiliary question: are these two declarations equivalent?
pred rel_test(r : univ -> univ)
pred rel_test(r : set univ -> univ)
The problem is that with the Forbid Overflow option set to No the integer semantics in Alloy is wrap around, and with the default scope of 3 (bits), then indeed 9=1, as you can confirm in the evaluator.
With the signatures a and b commented the biggest relation that can be generated with scope 2 has 4 tuples (since the max size of univ is 2), so the problem does not occur.
It also does not occur in the latest build because I believe it comes with the Forbid Overflow option set to Yes by default, and with that option the semantics of integers rules out instances where overflows occur, precisely the case when you compute the size of the relation with 9 tuples. More details about this alternative integer semantics can be found in the paper "Preventing arithmetic overflows in Alloy" by Aleksandar Milicevic and Daniel Jackson.
On the main question: what version of Alloy are you using? I'm unable to replicate the behavior you describe (using Alloy 4.2 of 22 Feb 2015 on OS X 10.6.8).
On the auxiliary question: it appears so. (The language reference is not quite as explicit as one might wish, but it begins one part of its discussion of multiplicities with "If the right-hand expression denotes a unary relation ..." and (in what I take to be the context so defined) "the default multiplicity is one"; the conditional would make no sense if the default multiplicity were always one.
On the other hand, the same interpretive logic would lead to the conclusion that the language reference believes that unary multiplicity keywords are only allowed before expressions denoting unary relations (which would appear to make r: set univ -> univ ungrammatical). But Alloy accepts the expression and parses it as set (univ -> univ). (The alternative parse, (set univ) -> univ, would be very hard to assign a meaning to.)

Equality in alloy

I've got an Alloy model which contains the following :
abstract sig person{}
one sig john,Steve extends person {Gender: man}
sig man{}
fact {
all name: person, Gender: man |
name.Gender = name.Gender => person =person}
How can I make equality between two signatures?
It's not clear from your question what you want to do, and from your sample Alloy code it looks as if you may be suffering from some confusions.
First, the model you show uses the name Gender in two different ways, which is not illegal in itself but seems to suggest some confusion. (It certainly confuses the willies out of this reader.)
In the declaration for the two singleton signatures john and Steve, Gender denotes two binary relations, one holding between the signature john and the signature man, the other holding between Steve and man. To say the same thing in symbolic form, Gender denotes (a) some subset of john -> man, and (b) some subset of Steve -> man.
In the anonymous fact, however, Gender denotes a variable of type man.
Your model will be easier to understand if you find a way to rename one or the other of these. Since variable names in a quantified expression are arbitrary, your fact will mean the same thing if you reformulate it as
fact { all P : person, M : man | P.M = P.M => person = person }
If that's not what you meant to say, then you may have meant to say something like
fact { all P : person, M : man |
P.Gender = P.Gender => person = person
}
Renaming the variable forces you to choose one meaning or the other. This is a good thing. (It is an unfortunate fact that neither formulation is actually satisfactory in Alloy. But let's deal with one problem at a time; getting rid of the double use of the name Gender is the first step.)
A second issue is that whichever formulation of the fact you meant, it almost certainly doesn't mean what you wanted it to mean. Ignoring the specifics of the model for a moment, your fact takes the form
fact { all V1 : sig1, V2 : sig2 |
Expression = Expression => sig1 = sig1
}
where Expression is either V1.V2 or V1.Relation, for some Relation defined in the model. There are several things wrong here:
V1.V2 is meaningless where V1 and V2 are both names of signatures or variables ranging over given signatures: the dot operator is meaningful only if one of its arguments is the name of a relation.
If any expression E is meaningful at all, then a Boolean expression of the form E = E (for example, person.Gender = person.Gender) is true regardless of what E means. Anything denoted by E is naturally going to be equal to itself. So the conditional might as well be written
1 = 1 => person = person
For the same reason, person = person will always be true, regardless of the model: for any model instance the set of persons in the instance will be identical to the set of persons in the instance. So the conditional will always be true, and the fact won't actually impose any constraint on instances of the model.
It's not clear how best to help you move forward. Perhaps one way to start would be to ask yourself which of the following statements you are trying to capture in your model.
There is a set of persons.
Some persons are males (have gender = 'man'). Others are not males.
John is a male individual.
Steve is a male individual.
John and Steve are distinct individuals.
If x and y are individuals with the same gender, then x and y are the same individual. I.e. no two individuals have the same gender.
Note that these statements cannot all be true at the same time. (If that's not obvious, you might do worse than try to figure out why. Alloy can be helpful in that effort.)
Good luck.

Resources