All men are mortals.
Socrates is a man.
Therefore, Socrates is a mortal.
Below an Alloy model to express that inference rule. Is that a good way to express the inference rule? Can you provide a better way to express it?
abstract sig man {}
// Socrates is a man
one sig Socrates extends man{}
one sig Plato extends man{}
one sig Aristotle extends man{}
one sig Earthly {
mortals: set man
}
// All men are mortal
fact All_men_are_mortal {
all m: man | m in Earthly.mortals
}
// Therefore, Socrates is mortal
assert Socrates_is_mortal {
Socrates in Earthly.mortals
}
check Socrates_is_mortal
To make it closer to the natural language formulation, you might write something like this:
assert Syllogism {
all Socrates: univ, Man, Mortal: set univ |
-- every man is mortal
Man in Mortal
-- Socrates is a man
and (Socrates in Man)
-- implies Socrates is mortal
implies Socrates in Mortal
}
check Syllogism
Interesting. I did this a couple of weeks ago.
In your definition you already put the that Socrates is a man in the sigs. this basically makes the syllogism superfluous since you already stated Socrates is a men.
I think that you therefore need a model where Socrates is not by definition in men.
In short, my version for the correct use of the syllogism
sig Men{}
one sig Socrates {}
check Correct {
all mortal, men : some Men + Socrates {
men in mortal
and
Socrates in men
=> Socrates in mortal
}
} for 5 Men
If you check this then there are no counterexamples, so we seem to be ok.
However, it is easy to screw up with Syllogism's:
All men are mortal.
Socrates is a mortal.
Therefore Socrates is a man.
This can be done in Alloy as follows
check Wrong {
all mortal, men : some Men + Socrates {
men in mortal
and
Socrates in mortal
=> Socrates in men
}
} for 5 Men
When we check this we get a version where Socrates is in moral but not in men.
You can find an html version here and the source for this here. These use the new proposed Alloy 5 markdown format.
Another alternative:
sig Mortal {}
sig Man extends Mortal {}
one sig Socrates extends Man {}
check {Socrates in Mortal}
Related
I am modeling a Google Docs-like inline commenting system in Alloy. Specifically, I'm modeling the UI interactions that the user can do. The constraints, in English, are that:
users can have any number of comments
users can have any number of comments composing at once
comments can be either composing or editing, not both
(eventually) users can expand one comment at a time to view it—text is truncated otherwise.
so far I have only modeled adding a new comment—or so I think! When I run the model below, I expect to see that Alloy cannot find any counterexamples, but it finds one where a comment is in both the composed and composing relations at a single time.
I think there may be something off in my mental model of how Alloy works in this case. I can't see how a comment would possibly be added to the composed relation here: I think init would set all the drafts to have empty relations there, and that the actions in Traces would preclude a comment ever being added to composed. BUT! I'm clearly wrong, since Alloy finds an example where composed is non-empty. Does anyone know what's actually happening here?
module inlineComments
open util/ordering [Time] as TimeOrdering
sig Time {}
sig Draft {
composing: set Comment -> Time,
composed: set Comment -> Time,
-- expanded: lone Comment -> Time,
}
sig Comment {}
-- What can we do with these?
pred newComment (t, t': Time, c: Comment, d: Draft) {
-- comment is not already known to us
c not in d.composing.t
c not in d.composed.t
-- start composing the comment
d.composing.t' = d.composing.t + c
}
pred init (t: Time) {
all d: Draft, c: Comment | c not in d.composing.t
all d: Draft, c: Comment | c not in d.composed.t
}
fact Traces {
init[TimeOrdering/first]
all t: Time - TimeOrdering/last |
let t' = TimeOrdering/next[t] |
some d: Draft, c: Comment |
newComment [t, t', c, d]
}
-- Is the world how we expect it to be?
assert validState {
-- comments cannot be composing and composed at the same time
all t: Time, d: Draft | d.composing.t & d.composed.t = none
}
check validState for 3 but 1 Draft
This is known as the "frame problem": you've specified that new comments can be put into composing, but not that nothing else happens! You have to make it explicit that the only way the system may change is via newComment. Here's one way you could do that:
fact Traces {
init[TimeOrdering/first]
all t: Time - TimeOrdering/last |
let t' = TimeOrdering/next[t] |
some d: Draft, c: Comment {
newComment [t, t', c, d]
d.composed.t = d.composed.t' -- d.composed doesn't change
}
}
Note this only works because you've exlicitly scoped to a maximum of 1 draft. If you test with two drafts, you also have to show that none of the drafts change in any way. If that will always be the case that there's only one Draft, you can write one sig Draft to enforce that.
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
Here are the signatures
one sig Library {
books: set Book,
patrons: set Patron,
circulation: Patron lone -> some Book
}
sig Book { }
sig Patron {
curbooks: set Book
}
Question ->What I want to do is : write a fact that the books currently with a patron are accounted in the library's circulation relation
fact curPatronBooksConsistent {
lone l : Library | all b : l.patrons.curbooks | b in l.circulation
}
Now I understand the nature of the error: in can be used only between 2 expressions of the same arity.
Left type = this/Book
Right type = this/Patron->this/Book
However I do not know how to nor can I find any examples of returning only a "set" of books that are associated with the library.circulation. I realize this is not a set but a relationship so how do I express that in Alloy?
all the books belonging to the patrons e.g. all p.curbooks are mapped in the l.circulation?
Thank you all in advance.
Welcome to Stack Overflow. You say
However I do not know how to nor can I find any examples of returning only a "set" of books that are associated with the library.circulation.
Look again at discussions of the dot (join) operator; you should find plenty of examples. The relation circulation is a ternary relation Library -> Patron -> Book. Your expression l.circulation performs a join and reduces the arity, producing a relation Patron -> Book.
How do you get a relation of the form Patron -> Book down to a set of books?
One obvious way is to join it to a set of Patrons with an expression like Patron.(l.circulation). That's probably not what you want -- you probably want to say that every book shown as in some patron's curbooks is checked out not just to some patron but to that particular patron.
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".