So I have the following:
some sig Person {
friends : set Person
}
fact TransitiveForThree {
one p1, p2, p3 : Person {
p1 in p2.friends && p2 in p3.friends => p1 in p3.friends
}
}
The idea is that I want there to exist a set of 3 people where they are all friends with each other. However I would like it to be that, there exists a set with at least 3 or more people who are all friends. Can someone explain how to do that with Alloy?
fact three_friends {some disj p, q, r : Person | p+q+r -> p+q+r in friends}
Untried! It does force the three Persons in the clique to be friends with themselves. You will need to set the scope to contain at least 3 Person.
sig Person {friends: set Person}
run {some s: set Person | #s >= 3 and s->s in friends}
Related
[Update] Thanks to #Loïc Gammaitoni for providing the answer. Based on Loïc's insight, this is the model I created to test for equivalence of the two approaches:
sig Key {}
sig Room {
keys: set Key
}
pred DisjointKeySet_v1 {
keys in Room lone -> Key
}
// See page 274 of Software Abstractions.
// It says that this: sig S {f: disj e}
// is equivalent to the constraint:
// all a,b: S | a != b => no a.f & b.f
pred DisjointKeySet_v2 {
all r, r': Room | r != r' => no r.keys & r'.keys
}
assert Equivalent {
DisjointKeySet_v1 iff DisjointKeySet_v2
}
check Equivalent
Each guest at a hotel is given a set of keys:
sig Key {}
sig Room {
keys: set Key
}
We must constrain the sets of keys so that no two guests get an identical key. Here's one approach to implementing that constraint:
fact DisjointKeySet {
keys in Room lone -> Key
}
A second approach to implementing the constraint involves modifying the declaration of keys:
sig Room {
keys: disj set Key
}
Are the two approaches equivalent?
I believe they are.
To be certain, I want the Alloy Analyzer to compare the two approaches and search for counterexamples.
How to do this? How to write the proper assert?
Below is an assert that I created. I think that it properly checks for equivalence of the two approaches. Do you agree? My assert seems rather round about. Is there a more direct way of showing equivalence?
sig Key {}
sig Room {
keys: disj set Key
}
// If each room has a disjoint set of keys,
// then each key may be used with only
// one room
assert Equivalent {
no k: Key, disj r, r': Room |
(k in r.keys) and (k in r'.keys)
}
check Equivalent
The keyword disj is in this context a shorthand for all a, b: Room| a!=b implies no a.keys & b.keys (c.f. Appendix B of Software Abstraction)
To answer your question, you could thus check the assertion:
assert equivalence {
(keys in Room lone -> Key) <=> (all a, b: Room| a!=b implies no a.keys & b.keys)
}
Results will suggest that both approaches are equivalent.
How do I write a function in Ally that returns a subset of the parameter:
fun subset( s : set univ ) : set univ {..}
I can write a predicate:
pred subset( disj a, b : set univ ) { b in a }
However, a function would be nicer to read but I am not sure how to put constraints on the return value?
I don't see any clean way to do it.
A dirty hack to achieve your goal would be to differentiate univ elements by, e.g., ranking them. To do so, I'd introduce an arbitrary signature in which a rank relation is defined, associating an integer to each univ element.
Then, returning an arbitrary subset would simply consist in removing from a given set elements who have e.g. the highest rank.
fun subset( s : set univ ) : set univ {
let maxRank= max[diff.rank[s]] |
s - diff.rank.maxRank
}
one sig diff{
// remove -Int if you plan to use your subset function on sets of Int as well
rank : (univ -Int) -> one Int
}
Below I create three sets: Name, Address, and Host. The addr field maps Name to Address. The host field maps Address to Host.
sig Name {
addr: Address
}
sig Address {
host: Host
}
sig Host {}
Here I ask the Alloy Analyzer to create an instance for the join of two relations: addr and host.
run {one addr.host} for 1
This is the graphic that is generated:
Next, I ask the Alloy Analyzer to create an instance for the join of three relations: addr, a ternary relation of identical atoms in each tuple, and host.
run {one addr.{a, b, c: univ | a = b and b = c}.host} for 1
Surprisingly, the graphic generated is identical to the one shown above. Why is this?
The visualizer shows an instance by giving values for each of the named relations and sets. Your second example still has only two named relations in it. If you want to see the value of a relation that is given just as an expression, you'll need to name it, eg like this:
run {some r: univ -> univ -> univ |
r = {a, b, c: univ | a = b and b = c} and
one addr.r.host} for 1
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.
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".