Sunteți pe pagina 1din 8

Lesson 0

back next
Approach of this Tutorial
The theme to this tutorial is "lead by mistake". We will present you with an Alloy model which is well formed, but
which initially makes some conceptual mistakes and has some shortcomings. We will then go through the process of
identifying those mistakes, understanding why they occurred, and xing them. We will iterate this process until we have
a nal draft.
We choose this approach, not only because it imitates the actual modeling process, but also because it will allow us to
begin with a simple model, using only a small part of Alloy syntax, and gradually introduce complexities and more
advanced syntax as it is needed. As a result, this tutorial will not introduce you to every Alloy command, but we will
make sure you are comfortable with the important ones. The rest can be found in sidenotes or in the reference manual.
Why Write a Model?
The goal of a writing a model is describe some aspect of a system (but not the entire system), constrain it to exclude ill-
formed examples, and check properties about it. For instance, you might describe the procedure a company uses to
reroute mail internally, add some constraints about how the mail carriers behave, and then check to see if each piece of
mail either gets to its destination or returned to sender. Your modeling tool (in this case, Alloy), would then either say
"this property always holds for problems up to size X" or "this property does not always hold, and here is a counter
example".
There are two kinds of problems that can arise:
bugs in the model itself. We will discuss the problems of overconstraining and underconstraining your model, and
how to nd and eliminate such bugs.
errors in the subject you are modeling. These are what you are after, and what modeling is all about. We will
show you how to make and check assertions about your system, and how to track down why a given assertion
failed to hold.
Alloy is similar to several other existing languages and modeling techniques, but with several key differences.
nite scope check - once you go to actually analyze the model, you must specify a scope (size) for your model.
The analysis is sound (it never returns false positives) but incomplete (since it only checks things up to a certain
scope). However, it is complete up to scope; it never misses a counterexample which is smaller than the specied
scope. Small scope checks are still extremely valuable for nding errors.
innite model - The models you write in Alloy do not reect the fact that the analysis is nite. That is, you
describe the compontents of a system and how they interact, but do not specify how many components there can
be (as is done in traditional "model checking").
declarative - a declarative modeler answers the question "how would I recognize that X has happened", as
opposed to an "operational" or "imperative" modeler who asks "how can I accomplish X".
automatic analysis - unlike some other declarative specication languages (such as Z and OCL, the object
language of UML), Alloy can be automatically analyzed. You can automatically generate examples of your system
and counterexamples to claims made about that system.
structured data - Alloy supports complex data structures, such as trees, and thus is a rich way to describe state
How Lesson I Will Work
We begin our tutorial with a simple model of a le system. It has a notion of a "le system object" which can be either a
le of a directory. Every le system object knows its parent, and directories also know their contents. We will also create
the notion of a "root directory", which resides at the top of the le system.
We will begin by dening les, directories, and le system objects, and make sure that they have the appropriate elds
(parent, contents, etc.). We then show how to write simple facts to constrain the le system and to impose simple sanity
constraints. For instance: every le system object must be either a le or a directory (not both, not neither); the le
system is connected, the root has not parent; and so on.
It is easy to forget simple constraints like this, since they are so obvious to our intuition. We will show you how to view
example le systems to make sure that they do not have any bizarre behaviour that you wished to preclude.
We will show you how to make assertions about properties you think (or hope) are true as a result of the sanity
constraints you wrote. We'll show you how to check these assertions, and what to do when they fail to hold. For instance,
we will verify that a le system is acyclic, even though we do not explicitly force it to be so.
The le system we write will have some shortcomings; most prominently, it will be static. In the following lessons, we
will introduce dynamic operations, such as move and delete.
By the end of the rst lesson, you will have written a simple static le system, constrained it to exclude ill-formed le-
systems, and veried some properties about it.
To backup to an earlier lesson, load the << previous lesson - tutorial instructions.
When you are ready to proceed, load the next lesson >> - File System Lesson I.
restart the tutorial from the beginning.
No model currently loaded.
How v3.0 differs from v2.0
back
open as sidenote
major changes
GUI and visualizer
An improved interface and greater visualizer customizability make it easier to understand counterexamples the analyzer
discovers. Details of the interface are given in the Alloy walkthrough.
subtypes
The introduction of subtypes (disjoint subsets) improves clarity and efciency, and allows more detailed specication of
scopes for improved scalability. Details of how to create subtypes are given below in the descriptions of 'extends' and
'abstract'.
sig student extends slave {} //subtype
sig happy in emotion {} //subset
atomization
Atomization is an improvement to efciency which is invisible to the user (although some of the new features are only
possible because of it).
parametric polymorphism
When you import a parametric module (such as ordering.als), you now pass it a signature name (or a comma-ed list of
signature names). This replaces the old implicity polymorphism.
module tutorial/example
open ordering[State]
sig State {}
...
overloaded eld names Signatures now have their own namespaces; you can declare elds in two subsignatures of a
common signature that have the same name, and they will be (automatically) disambiguated by context.
Int
Int is now a signature, although this does not affect the user.
keyword changes
extends --> in, extends
If you want one signature to be a subset of another, like the old extends keyword, you now write in. If you write
extends, you create subtypes instead of subsets -- subtypes are just subsets which are disjoint from each other. As a
consequence, disj is no longer needed for signatures.
sig Person, Puppet {}
//subsets:
sig Happy, Ugly in Person{}
//subtypes are disjoint subsets:
sig Student, Faculty, Staff extends Person {}
One of the benets of subtypes is that you now have more control over the scope you wish to analyze. If unspecied, the
scope of a subtype defaults to that of its supertype (just like subsets). However, you can also specify it manually to
improce scalability of your model.
For example, one can now write
check fibbles for 6 Person, 2 Staff
and restrict Alloy to not bother examining cases where more than 2 of the Persons are Staff.
disj gone
disj no longer applies to signature declarations. If you want disjoint subsets like the old disj achieved, instead create
subtypes with the extends keyword.
However, note that disj can still be used when specifying quantied variables, as in
all disj a,b: Foo | ...
abstract added
abstract signatures have no elements/instantiations except for those that are also elements/instantiations of its
subtypes. Subtypes that extend an abstract signature partition it.
Exception: if an abstract signature has no subtypes (no signatures extend it), then the abstract keyword is ignored and it
may have elements/instantiations as usual.
part gone
part can no longer be written before a declaration of several signatures to indicate a partition. Instead, make the
partitioning signatures subtypes (rather than subsets) using the extends keyword, and make the their supertype
abstract. Thus, the old
sig numeral {}
disj sig roman, arabic extends numeral {}
would now be written
abstract sig numeral {}
sig roman, arabic extends numeral {}
static --> one
static is now written one, which is consistent with the way one is used as a quantier. In both cases, it means
'exactly one'. That is, when you write one before a signature declaration, you force there to be exactly one copy of that
signature. For example:
one Root extends Directory {}
fun --> fun, pred
the old fun keyword has been split into fun, which declares a function that evalues to a value, and pred, which
declares a predicate that evaluates to either true or false. That is, a function is an expression while a predicate is a
formula. For example:
sig Widget {}
//returns the union of the given sets
fun InCommon (n1, n2: set Widget) : Widget {
n1 + n2
}
//check that a union has been performed
pred InCommon (n1, n2, n3: set Widget) {
n1 + n2 = n3
}
$ gone, <: and :> added
overloading has been improved; <: and :> have replaced $.
in general, <: anmd :> are domain restriction operators, and operate the same as in the modeling language Z.
with gone, @ added
The keyword with no longer used. Add the prex @ to preempt implicit eld dereferencing in an appended fact.
:: changed
:: no longer denotes relational join (.). Instead, :: replaces .. to denote a receiver for a function call. That is,
x..f(y) is now written x::f(y), and makes sure that x has the same value as the expression denoted by f(y).
exactly added
When specifying scopes in a run or check statement, you can say exactly. For example,
check Fibbles for 6 Apple, exactly 4 Orange
will examine cases where there are up to 6 Apples and precisely 4 Oranges.
option, sole --> lone
lone replaces sole as the quantier and predicate denoting 'zero or one'.
fact maybe {
lone solution
lone s: solution | ...
}
Furthermore, lone replaces option in eld declarations.
sig item {}
sig list {
head: item
next: lone list
}
multiplicity: +, !, ? --> some, one, lone
The terms some, one, and lone replace the symbols +, !, and ? respectively as multiplicity markeings on relations.
some allowed in eld declarations
some can be in eld declarations, e.g. just like set. For example,
sig Player {}
sig Game {players: some Player}
univ, none, iden changed
univ is now the common supertype of all atoms. there is no more univ[e] function that returns the type of the
expression e.
none is now the empty set of univ. there is no more none[e] function that returns the empty set of the type of
expression e
iden is now the identity function from univ->univ. there is no more iden[e] function that returns the identity
relation over the type of e
exh gone
instead of writing
exh a1,a2:A
you now write
A in a1+a2
The keyword part is also gone, but disj can still be used in this manner.
For a more detailed description of how these changed were implemented, and the benets they provide to analysis, see
the description on the Alloy website of what's new in Alloy 3.
return to tutorial intructions
restart the tutorial from the beginning.

S-ar putea să vă placă și