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)?
Related
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).
/*
sig a {
}
sig b {
}
*/
pred rel_test(r : univ -> univ) {
# r = 1
}
run {
some r : univ -> univ {
rel_test [r]
}
} for 2
Running this small test, $r contains one element in every generated instance. When sig a and sig b are uncommented, however, the first instance is this:
In my explanation, $r has 9 tuples here and still, the predicate which asks for a one tuple relation succeeds. Where am I wrong?
An auxiliary question: are these two declarations equivalent?
pred rel_test(r : univ -> univ)
pred rel_test(r : set univ -> univ)
The problem is that with the Forbid Overflow option set to No the integer semantics in Alloy is wrap around, and with the default scope of 3 (bits), then indeed 9=1, as you can confirm in the evaluator.
With the signatures a and b commented the biggest relation that can be generated with scope 2 has 4 tuples (since the max size of univ is 2), so the problem does not occur.
It also does not occur in the latest build because I believe it comes with the Forbid Overflow option set to Yes by default, and with that option the semantics of integers rules out instances where overflows occur, precisely the case when you compute the size of the relation with 9 tuples. More details about this alternative integer semantics can be found in the paper "Preventing arithmetic overflows in Alloy" by Aleksandar Milicevic and Daniel Jackson.
On the main question: what version of Alloy are you using? I'm unable to replicate the behavior you describe (using Alloy 4.2 of 22 Feb 2015 on OS X 10.6.8).
On the auxiliary question: it appears so. (The language reference is not quite as explicit as one might wish, but it begins one part of its discussion of multiplicities with "If the right-hand expression denotes a unary relation ..." and (in what I take to be the context so defined) "the default multiplicity is one"; the conditional would make no sense if the default multiplicity were always one.
On the other hand, the same interpretive logic would lead to the conclusion that the language reference believes that unary multiplicity keywords are only allowed before expressions denoting unary relations (which would appear to make r: set univ -> univ ungrammatical). But Alloy accepts the expression and parses it as set (univ -> univ). (The alternative parse, (set univ) -> univ, would be very hard to assign a meaning to.)
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.
I was inspired by the slide http://alloy.mit.edu/alloy/tutorials/day-course/s4_dynamic.pdf of Greg Dennis and Rob Seater, to model an automaton whose transitions are defined by rules and invariances but I can not understand why satisfy the constraints even in the presence of invariances and contradictory rules.
sig State {value : one Int}
sig System { trans : State -> State }
pred i1[s : State] { s.value < 4 }
pred i2[s : State] { s.value > 0 }
pred r1[s, s' : State, m, m' : System] {
s.value = -1 and s'.value = 0 and change[s, s', m, m']
}
pred r2[s, s' : State, m, m' : System] {
s.value = 1 and s'.value = 2 and change[s, s', m, m']
}
pred change[s, s' : State, m, m' : System] {
m'.trans = m.trans + s -> s'
}
assert ruleSafe {
all s, s' : State, m,m' : System |
i1[s] and i2[s] and r1[s,s',m,m'] and r2[s,s',m,m'] =>
i1[s'] and i2[s']
}
check ruleSafe
First, a side note: It's not clear what the value relation is intended to be doing, but do remember that integers in Alloy tend to be very narrow and overflow behavior can make rules like s.value < 4 produce unexpected results. Whenever integers are used only to ensure a nice supply of distinct values, or ordered values it is almost always better to use an uninterpreted type in Alloy with some relations to ensure the necessary constraints.
However, that's not the main source of your confusion. I think you believe that since r1 requires its first argument to have a value of -1 and r2 requires the same argument to have a value of 1, any condition involving both r1 and r2 with the same first argument cannot possibly be satisfied, and there can be no instances of a model which is required to satisfy such a predicate. Almost true!
I think you're correct that r1 and r2 cannot both be true for the same set of arguments (or any sets of arguments with the same first argument s). But the constraint you specify uses r1[s,s',m,m'] and r2[s,s',m,m'] in the antecedent of a conditional. Before you go any further, stop and think: What is the truth value of a conditional if the antecedent is false?
If you are having trouble seeing what is going on, try examining the instances of your model in which the antecedent of your conditional is true for all pairs of States and Systems. Concretely, add the following to your model and look at the instances it produces.
pred antecedent {
all s, s' : State, m, m' : System
| i1[s] and i2[s] and r1[s,s',m,m'] and r2[s,s',m,m']
}
run antecedent
It took me a minute or two before I understood what I was seeing; if it takes you longer than a few minutes, you might try the following variant definition of antecedent and see if it enlightens you.
pred antecedent {
all s, s' : State, m, m' : System
| i1[s] and i2[s] and r1[s,s',m,m'] and r2[s,s',m,m']
some State
some System
}
You are not the first user of first-order logic to have been taken by surprise when a conditional statement in your model turned out to be vacuously true when you expected it to be false. You won't be the last.
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.