Suppose we have the following Alloy model:
abstract sig Season {}
one sig Spring, Summer, Fall, Winter extends Season {}
abstract sig Student {
bornIn: one Season
}
abstract sig Freshman, Sophomore extends Student {}
one sig John, Walter extends Freshman {}
one sig Sarah extends Sophomore {}
pred isCompatibleWith(s1, s2: Student) {
s1.bornIn = s2.bornIn
}
I want to say that Sarah the Sophomore mustn't be compatible with any Freshman.
fact {
not Sarah.isCompatibleWith[Freshman]
}
Alloy is satisfied with my syntax. I add an assertion:
assert WhyDoesThisNotHold {
not Sarah.isCompatibleWith[John]
}
But Alloy finds a counter-example: Sarah and John are both born in the Summer!
Whereas when I change the fact to this, Alloy does not find a counter-example:
fact {
no f: Freshman | Sarah.isCompatibleWith[f]
}
What's the difference between the two syntaxes, and why does the first one not work as I intend? (And since it's valid Alloy syntax, what's it actually saying?)
Your first fact doesn't behave as you expect because you call the predicate isCompatibleWith with the set of all Freshman as parameter, however this predicate is not meant to check the compatibility between two sets of students. (it could be by replacing the = symbol by the intersection operator& and check that the resulting set is empty.
I will now show you how this fact doesn't prevent John and Sarah to be compatible.
Suppose that Sarah and John are born in Summer and Walter in Winter, then the fact holds because :
not Sarah.isCompatibleWith[Freshman] = not Sarah.isCompatibleWith[Walter+John]
= not Sarah.bornIn=(Walter+John).bornIn
= not Summer = (Summer+Winter)
= not false
= true
Related
How can I write out a literal for a sig in Alloy? Consider the example below.
sig Foo { a: Int }
fact { #Foo = 1 }
If I execute this, I get
| this/Foo | a |
|----------|---|
| Foo⁰ | 7 |
In the evaluator, I know I can get a reference to the Foo instance with Foo$0 but how can I write a literal that represents the same value?
I've tried {a: 7}, but this is not equal to Foo$0. This is intentionally a trivial example, but I'm debugging a more complex model and I need to be able to write out literals of sigs with multiple fields.
Ah, this is one of the well hidden secrets! :-) Clearly in your model you cannot refer to atoms since the model is defining all possible values of those atoms. However, quite often you need your hands on some atom to reason about it. That is, you want to be able to name some objects.
The best way to get 'constants' is to create a predicate you call from a run clause. In this predicate, you define names for atoms you want to discuss. You only have to make sure this predicate is true.
pred collision[ car1, car2 : Car, road : Road ] {
// here you can reason about car1 and car2
}
run collision for 10
Another way is to create a quantification whenever you need to have some named objects:
run {
some car1, car2 : Car, road : Road {
// here you can reason about car1 and car2 and road
}
} for 10
There was a recent discussion to add these kinds of instances to the language so that Kodkod could take advantage of them. (It would allow faster solving and it is extremely useful for test cases of your model.) However, during a discussion this solution I presented came forward and it does not require any new syntax.
try to put a limitation for 'Integer' in the 'run' command. I mean :
sig Foo {a : Int}
fact{ #Foo = 1}
pred show {}
run show for 1 Foo, 2 Int
I have the following specification in Alloy:
sig A {}
sig Q{isA: one A}
fact {
all c1,c2:Q | c1.isA=c2.isA => c1=c2 // injective mapping
all a1:A | some c1:Q | c1.isA=a1 //surjective
}
In my models the above fact repeats similarly between different signature. I tried to factor out it as a separate module so I created a module as below:
module library/copy [A,Q]
fact {
all c1,c2:Q | c1.isA=c2.isA => c1=c2 // injective mapping
all a1:A | some c1:Q | c1.isA=a1 //surjective
}
Then I tries to use it as bellow:
module family
open library/copy [Person,QP]
sig Person {}
sig QP{isA:Person}
run {} for 4
but Alloy complains that "The name "isA" cannot be found." in the module.
What is wrong with my approach? and Why alloy complains?
In my previous answer I tried to address your "similarly between different signature" point, that is, I thought your main goal was to have a module that somehow enforces that there is a field named isA in the sig associated with parameter Q, and that isA is both injective and surjective. I realize now that what you probably want is reusable predicates that assert that a given binary relation is injective/sujective; this you can achieve in Alloy:
library/copy.als
module copy [Domain, Range]
pred inj[rel: Domain -> Range] {
all c1,c2: Domain | c1.rel=c2.rel => c1=c2 // injective mapping
}
pred surj[rel: Domain -> Range] {
all a1: Range | some c1: Domain | c1.rel=a1 //surjective
}
family.als
open copy[QP, Person]
sig Person {}
sig QP{isA:Person}
fact {
inj[isA]
surj[isA]
}
run {} for 4
In fact, you can open the built-in util/relation module and use the injective and sujective predicates to achieve the same thing, e.g.:
family.als
open util/relation
sig Person {}
sig QP{isA:Person}
fact {
injective[isA, Person]
surjective[isA, Person]
}
run {} for 4
You can open the util/relation file (File -> Open Sample Models) and see a different way to implement these two predicates. You can then even check that your way of asserting injective/surjective is equivalent to the built-in way:
open copy[QP, Person]
open util/relation
sig Person {}
sig QP{isA:Person}
check {
inj[isA] <=> injective[isA, Person]
surj[isA] <=> surjective[isA, Person]
} for 4 expect 0 // no counterexample is expected to be found
Modules in Alloy are treated as independent units (i.e., a module can access only the stuff defined in that module itself and the modules explicitly opened in that module), so when compiling the "copy" module, isA is indeed undefined. A theoretical solution would be to additionally parametrize the "copy" module by the isA relation, but in Alloy module parameters can only be sigs.
A possible solution for your problem would be to define abstract sigs A and Q in module "copy", and then in other modules define concrete sigs that extend A and Q, e.g.,
copy.als:
module library/copy
abstract sig A {}
abstract sig Q {isA: one A}
fact {
all c1,c2:Q | c1.isA=c2.isA => c1=c2 // injective mapping
all a1:A | some c1:Q | c1.isA=a1 //surjective
}
family.als:
open library/copy
sig Person extends A {}
sig QP extends Q {} {
this.#isA in Person // restrict the content of isA to Person
}
run {} for 4
Using inheritance to achieve this kind of code reuse is conceptually not ideal, but in practice is often good enough and I can't think of another way to do it 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.
The Alloy 4 grammar allows signature declarations (and some other things) to carry a private keyword. It also allows Allow specifications to contain enumeration declarations of the form
enum nephews { hughie, louis, dewey }
enum ducks { donald, daisy, scrooge, nephews }
The language reference doesn't (as far as I can tell) describe the meaning of either the private keyword or the enum construct.
Is there documentation available? Or are they in the grammar as constructs that are reserved for future specification?
This is my unofficial understanding of those two keywords.
enum nephews { hughie, louis, dewey }
is semantically equivalent to
open util/ordering[nephews] as nephewsOrd
abstract sig nephews {}
one sig hughie extends nephews {}
one sig louis extends nephews {}
one sig dewey extends nephews {}
fact {
nephewsOrd/first = hughie
nephewsOrd/next = hughie -> louis + louis -> dewey
}
The private keyword means that if a sig has the private attribute, its label is private within the same module. The same applies for private fields and private functions.
In addition to the previous accepted answer, I'd like to add some useful insights coming from a one-week experience with Alloy on enums, in particular on the main differences with standard sig.
If you use abstract sig + extend, you'll come up with a model in which there are many sets corresponding to the same concept. Maybe an example could clarify it better.
Suppose somthing like
sig Car {
dameges: set Damage
}
You have the choice to use
abstract sig Damage {}
sig MajorDamage, MinorDamage extends Damage {}
vs
enum Damage {
MajorDamage, MinorDamage
}
In the first case we can come up wiht a model with different MinorDamage atoms (MinorDamage0, MinorDamage1, ...) associatet to Cars, while in the second case you always have only one MinorDamage to which different Cars can refer.
It could have some sense in this case to use an abstract sig + extend form (because you can decide to track different MinorDamage or MajorDamage elements).
On the other hand, if you want to have a currentState: set State, it could be better to use an
enum State {Damaged, Parked, Driven}
to map the concept, in order to have exactly three State to which each Car can refer to. In this way, in the Visualizer, you can decide to project your model on exactly one of the states and it will highlight all the Cars associated to this state. You can't do that with the abstract + extend construct, of course, because projecting over MajorDamage0 will highlight only the Car associated to that Damage and nothing else.
So, in conclusion, it really depends on what you have to do.
Also, keep in mind that if you have an enum composed by X elements and execute
run some_predicate for Y
where Y < X, Alloy produces no instance at all.
So, in our last example, we can't have a Y < 3.
As a last note, enums don't always appear in the Visualizer if you use the Magic Layout button, but as I said previously you can "project" your model over the enum and switch between the different elements of the enum.
This is homework and I'm having a lot of trouble with it. I am using Alloy to model a library. Here are the definitions of the objects:
sig Library {
patrons : set Person,
on_shelves : set Book,
}
sig Book {
authors : set Person,
loaned_to : set Person,
}
sig Person{}
Then we need to have to have a fact that states, every book is either on the shelf, or taken out by a patron. However, they cannot be in both places.
// Every book must either be loaned to a patron or
// on the shelves.
fact AllBooksLoanedOrOnShelves {}
I have tried this...
fact AllBooksLoanedOrOnShelves {
some b : Book {
one b.loaned_to =>
no (b & Library.on_shelves)
else
b in Library.on_shelves
}
}
But it's not working... the books always are on the shelves. want to say, "For every book, if it is not being loaned, it is on the shelf. Otherwise, it's out."
Corrections, examples, and hints are greatly appreciated.
If every book must be either on loan to someone or on the shelves, then (a) no book will be both on loan and on the shelves (assuming you mean that "or" as exclusive), so the intersection of the onloan set and the onshelf set will be empty, and (b) the set of books will be equal to the union of the onloan and onshelf sets.
The set of books on loan at any time is the domain of the loaned_to relation. The set of books on the shelf in a given library L is the value of L.onshelves; the set of books on the shelves in all known libraries is Library.onshelves.
So you might say
fact in_or_out_not_both {
no Library.onshelves & loaned_to.Person
}
fact all_books_in_or_out {
Book = Library.onshelves + loaned_to.Person
}
Or you might need to say slightly different things, depending on just what you mean. Note that these constraints don't say that a book on loan must be on loan to a single borrower.
Your fact is wrong. You want to say something for all books (not "some"). And that something is basically an XOR.
Here's one that works:
fact AllBooksLoanedOrOnShelves{
all b : Book|
(b in Library.on_shelves and no p:Person | p in b.loaned_to)
or
(not b in Library.on_shelves and one p:Person | p in b.loaned_to)
}
Ok correct me if I'm wrong, but I believe this is the fact you're after:
fact {
disj[Library.on_shelves, Person.~loaned_to]
}
And a little explanation. Library.on_shelves is the set of books on the right side of the on_shelves relation, i.e. all the books that are on the shelves. ~loaned_to is the reverse relation of type Person -> Book and Person.~loaned_to is the set of books loaned to any person.
The disj predicate declares that the two sets have no common atoms (disjoint sets).
I am not very familiar with Alloy.
But I think this or something similar would work.
Every book is either on the shelves or is loaned to a a patron.
fact AllBooksLoanedOrOnShelves {
all b: Book | b in Library.on_shelves || b.loaned_to in Library.patrons
}
This question is 6 years old now, but I'm learning Alloy, and I wanted to offer my take on a solution.
fact AllBooksLoanedOrOnShelves {
no (Library.on_shelves & loaned_to.Person)
}
This can be read as "the intersection of the set of books that are on shelves and the set of books that are loaned out, is empty".