Subset signatures in Alloy argument declarations - are they not checked? - alloy

I am getting unexpected results in an Alloy model. Consider the following model which describes a few aspects of responses to HTTP requests:
// Code: an HTTP return code
abstract sig Code {}
one sig rc200, rc301, rc302 extends Code {}
// State: the current state of a resource
sig State {}
// subsets of State: some resources are green, some red
// (also: some neither, some both)
sig Green in State {}
sig Red in State {}
// Response: a return code + state pair
sig Response {
rc : one Code,
entity_body : lone State
}
// some subclasses of Response
sig R200_OK in Response {}{ rc = rc200 }
sig R301_Moved_Permanently in Response {}{ rc = rc301 }
sig R302_Found in Response {}{ rc = rc302 }
// a Response is red/green if its entity body is Red/Green
pred green[ R : R200_OK ] { R.entity_body in Green }
pred red[ R : R200_OK ]{ R.entity_body in Red }
assert A {
all R : Response | green[R] implies R.rc = rc200
}
check A for 3
Because the predicates green and red declare their argument as being of type R200_OK, I expect that these predicates will be true only for atoms in the relation R200_OK, and other Responses (e.g. a Response with rc = rc301) will satisfy neither predicate. This expectation is expressed by assertion A.
To my surprise, however, when asked to check assertion A, the Alloy Analyzer produces what it says is a counterexample, involving a Response which is not in the relation R200_OK. (I first encountered this unexpected behavior in 4.2, build 2012-09-25; the current build of 2014-05-16 behaves the same way.)
Section B.7.3 Declarations of the language reference says "A declaration introduces one or more variables, and constrains their values and type. ... The relation denoted by each variable (on the left) is constrained to be a subset of the relation denoted by the bounding expression (on the right)." Am I wrong to read this as entailing that the only atoms which should satisfy the predicates red and green are atoms in the relation R200_OK? Or is something else going on?

They are checked.
The phenomenon you are pointing out in your question is explained in the Software Abstraction Book page 126.
It's basically written that the type checker will report an error if and only if the type of the argument declared in the predicate and the type of the value given as parameter during invocation are disjoint.
In your case, R200_OK and Response are not disjoint, hence the absence of error.
You could rewrite your predicate as follows :
pred green[ R : Response ] {R in R200_OK and R.entity_body in Green }
To illustrate the type checker's behavior extensively, you can consider the following example
sig A,B extends C{}
sig C{ c: set univ}
pred testExtend[a:A]{
a.c!= none
}
run {testExtend[A]} // works as expected
run {testExtend[B]} // error as A and B are disjoint
run {testExtend[C]} // no error as A and C are not disjoint
sig D,E in F{}
sig F{ f: set univ}
pred testIn[d:D]{
d.f!= none
}
run {testIn[D]} // works as expected
run {testIn[E]} // no error as E and D are not disjoint
run {testIn[F]} // no error as E and F are not disjoint
I would also like to put under your attention that you use the keyword in rather than extends , in the declaration of your 3 kinds of responses, which implies that :
A same response can be of different kind (i.e. a R200_OK response can also be a R302_Found)
A Response can also be neither R200_OK nor R302_Found, nor R301_Moved_Permanently.
It might not be what you want to express.

Related

Alloy pred/fun parameter constraint

The following Alloy predicate p has a parameter t declared as a singleton of type S. Invoke run p gives the correct result because the predicate body states that t may contain two different elements s and s'. However, in the second run command, a set of two disjoint elements of type S is passed into predicate p and this command gives an instance. Why is it the case?
sig S {}
pred p(t: one S) {
some s, s': t | s != s'
}
r1: run p -- no instance found
r2: run { -- instance found
some disj s0, s1: S {
S = s0 + s1
p[S]
}
}
See https://stackoverflow.com/a/43002442/1547046. Same issue, I think.
BTW, there's a nice research problem here. Can you define a coherent semantics for argument declarations that would be better (that is, simpler, unsurprising, and well defined in all contexts)?

Replacing recursion with transitive closure (reachability and productivity of non-terminals)

Sometimes, when I would like to use recursion in Alloy, I find I can get by with transitive closure, or sequences.
For example, in a model of context-free grammars:
abstract sig Symbol {}
sig NT, T extends Symbol {}
// A grammar is a tuple(V, Sigma, Rules, Start)
one sig Grammar {
V : set NT,
Sigma : set T,
Rules : set Prod,
Start : one V
}
// A production rule has a left-hand side
// and a right-hand side
sig Prod {
lhs : NT,
rhs : seq Symbol
}
fact tidy_world {
// Don't fill the model with irrelevancies
Prod in Grammar.Rules
Symbol in (Grammar.V + Grammar.Sigma)
}
One possible definition of reachable non-terminals would be "the start symbol, and any non-terminal appearing on the right-hand side of a rule for a reachable symbol." A straightforward translation would be
// A non-terminal 'refers' to non-terminals
// in the right-hand sides of its rules
pred refers[n1, n2 : NT] {
let r = (Grammar.Rules & lhs.n1) |
n2 in r.rhs.elems
}
pred reachable[n : NT] {
n in Grammar.Start
or some n2 : NT
| (reachable[n2] and refers[n2,n])
}
Predictably, this blows the stack. But if we simply take the transitive closure of Grammar.Start under the refers relation (or, strictly speaking, a relation formed from the refers predicate), we can define reachability:
// A non-terminal is 'reachable' if it's the
// start symbol or if it is referred to by
// (rules for) a reachable symbol.
pred Reachable[n : NT] {
n in Grammar.Start.*(
{n1, n2 : NT | refers[n1,n2]}
)
}
pred some_unreachable {
some n : (NT - Grammar.Start)
| not Reachable[n]
}
run some_unreachable for 4
In principle, the definition of productive symbols is similarly recursive: a symbol is productive iff it is a terminal symbol, or it has at least one rule in which every symbol in the right-hand side is productive. The simple-minded way to write this is
pred productive[s : Symbol] {
s in T
or some p : (lhs.s) |
all r : (p.rhs.elems) | productive[r]
}
Like the straightforward definition of reachability, this blows the stack. But I have not yet found a relation I can define on symbols which will give me, via transitive closure, the result I want. Have I found a case where transitive closure cannot substitute for recursion? Or have I just not thought hard enough to find the right relation?
There is an obvious, if laborious, hack:
pred p0[s : Symbol] { s in T }
pred p1[s : Symbol] { p0[s]
or some p : (lhs.s)
| all e : p.rhs.elems
| p0[e]}
pred p2[s : Symbol] { p1[s]
or some p : (lhs.s)
| all e : p.rhs.elems
| p1[e]}
pred p3[s : Symbol] { p2[s]
or some p : (lhs.s)
| all e : p.rhs.elems
| p2[e]}
... etc ...
pred productive[n : NT] {
p5[n]
}
This works OK as long as one doesn't forget to add enough predicates to handle the longest possible chain of non-terminal references, if one raises the scope.
Concretely, I seem to have several questions; answers to any of them would be welcome:
1 Is there a way to define the set of productive non-terminals in Alloy without resorting to the p0, p1, p2, ... hack?
2 If one does have to resort to the hack, is there a better way to define it?
3 As a theoretical question: is it possible to characterize the set of recursive predicates that can be defined using transitive closure, or sequences of atoms, instead of recursion?
Have I found a case where transitive closure cannot substitute for recursion?
Yes, that is the case. More precisely, you found a recursive relation that cannot be expressed with the first-order transitive closure (that is supported in Alloy).
Is there a way to define the set of productive non-terminals in Alloy without resorting to the p0, p1, p2, ... hack? If one does have to resort to the hack, is there a better way to define it?
There is no a way to do this in Alloy. However, there might be a way to do this in Alloy* which supports higher-order quantification. (The idea would be to describe the set of productive elements with a closure over the relation of "productiveness", which would use second-order quantification over the set of productive symbols, and constraining this set to be minimal. Similar idea is described in "A.1.9 Axiomatizing Transitive Closure" in the Alloy book.)
As a theoretical question: is it possible to characterize the set of recursive predicates that can be defined using transitive closure, or sequences of atoms, instead of recursion?
This is an interesting question. The wiki article mentions relative expressiveness of second order logic when transitive closure and fixed point operator are added (the later being able to express forms of recursion).

specifying properties of relations in alloy

I am trying to express certain mathematical properties of relations in Alloy, but I am not sure if I have the right approach yet, as I am just a beginner. Would appreciate any insights from the community of experts out there!
Specifying the fact that domain of a relation as singleton. e.g. Is the following a reasonable and correct way to do that?
pred SingletonDomain(r: univ->univ) {
one ~r
}
sig S2 {}
sig S1 {
child: set S2
}
fact {
SingletonDomain [child]
}
or should it be something like the following
pred SingletonDomain (r: univ->univ) {
#S2.~r = 1
}
This is not very modular since the use of S2 is very specific to the particular signature.
Specifying the fact that a relation is a total order. At the moment I am using the following, basically I am simulating xor
pred total[r: univ->univ] {
all disj e, e': Event | (e.r = e' and e'.r != e) or (e.r != e' and e'.r = e)
}
Thanks
To specify the fact that the domain of a given relation is a singleton, your first attempt is really close to do the trick. The only problem is that one ~r enforces the inverse of the r relation (and thus the r relation itself) to be composed of a single tuple. This is not what you want to express.
What you want to express is that all elements in the range of the r relation have the same (so only one) image through its inverse relation '.
You should thus write the following predicate :
pred SingletonDomain(r: univ->univ) {
one univ.~r
}
For your second question, your predicate doesn't handle cases were e -> e' -> e '' -> e. To handle those, you can use transitive closure.

What's wrong with this Alloy code?

I get a syntax error message for the code below.
The message designates the marked position in the addLocal assertion, stating:
"Syntax error at line 30 column 9: There are 1 possible tokens that can appear here: )"
I just can't see what's wrong here.
abstract sig Target{}
sig Addr extends Target{}
sig Name extends Target{}
sig Book
{
addr: Name->Target
}
pred add(b, b1:Book, n:Name, t:Target)
{
b1.addr = b.addr + (n->t)
}
fun lookup (b: Book, n: Name): set Addr
{
n.^(b.addr) & Addr
}
assert addLocal
{
all
b,b1:Book,
n,n1:Name,
t:Target |
add(b, b1, n, t) and n != n1 => lookup(b, n1) = lookup(b1, n1)
// |- error position
}
For reasons I never quite understood, at some point Alloy's syntax changed from using (or allowing) parentheses around the arguments to predicates and functions, to requiring square brackets. So the relevant line of addLocal needs to be re-punctuated:
add[b, b1, n, t] and n != n1 => lookup[b, n1] = lookup[b1, n1]
I don't have the grammar firmly enough in my head to be sure, but a quick glance at the grammar in appendix B of Software abstractions suggests that parentheses can wrap the arguments in the predicate declaration, but not in a predicate reference; in an expression position, parentheses always wrap a single expression, which would explain why the parser stops when it encounters the first comma in the argument list.

How to reuse facts by means of modules in Alloy

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.

Resources