Is there a reasonable way to denote that n elements need to be distinct from each other? Specifically, I have a sig similar to this one:
sig Node {
up: lone Node,
left: lone Node,
right: lone Node,
left_down: lone Node,
right_down: lone Node
}
and want to write a fact, that defines these to be distinct for any given Node. I am fairly certain I could just write it down as NxN matrix, like this:
fact {
all n: Node | n.up != n.left && n.up != n.right && n.up != n.left_down ...
}
but that seems extremely verbose and rather ugly. What is the proper way to do this?
The fact your suggested expresses that each set should be different, not that each set are disjoint. To check that sets are disjoint, you can simply check that their intersection (&) is empty.
You could thus write :
sig Node {
up: lone Node,
left: lone Node,
right: lone Node,
left_down: lone Node,
right_down: lone Node
}{
up & left=none and
right & left_down=none and
(up + left )& (right + left_down)=none and
(up + left + right + left_down)&right_down=none
}
A less verbose but uglier way of doing things would be by summing up the intersection of each node with those sets and ensure that the sum is always zero or one.
sig Node {
up: lone Node,
left: lone Node,
right: lone Node,
left_down: lone Node,
right_down: lone Node
}{
all n:Node | add[add[add[add[#(n&up),#(n&left)],#(n&right)],#(n&left_down)],#(n&right_down)] in 0+1
}
Related
I have a model (see below) with two signatures: Data and Node. I have defined some predicates which characterise inhabitants of Node, namely: Orphan, Terminal, and Isolated.
What I want to do - but have not yet achieved - is to define a predicate Link which models the linking of two Node such that one Node becomes the successor (succ) of the other. Moreover, I would like to restrict the operation such that links can only be made to Isolated Nodes. Furthermore, I would like the restriction - if it is possible - to somehow be internal to the Link predicate.
Here is my latest attempt:
sig Data {}
sig Node {
data: Data,
succ: lone Node
}
// Node characterisation
pred Isolated (n: Node) { Orphan[n] and Terminal[n] }
pred Orphan (n: Node) { no m: Node | m.succ = n }
pred Terminal (n: Node) { no n.succ }
/*
* Link
*
* May only Link n to an m, when:
* - n differs from m
* - m is an Isolated Node (DOES NOT WORK)
*
* After the operation:
* - m is the succcessor of n
*/
pred Link (n,m: Node) {
n != m
Isolated[m] /* Not satisfiable */
m = succ[n]
}
pred LinkFeasible { some n,m: Node | Link[n,m] }
run LinkFeasible
Including the conjunct Isolated[m] renders the model unsatisfiable. I think I understand why: there can be no Node which is both Isolated and a successor of another. I include it only in the hope that it might reveal my intentions.
My question: how do I define the Link predicate to link two Nodes such that only Isolated nodes may be linked-to?
The problem is that you want Link to be an operation which changes the value of succ. In order to model change in Alloy, you need to add an ordered signature which represents the distinct states of your system. So your signature would look something like this:
open util/ordering[time]
sig Time {}
sig Data {}
sig Node {
data: Data,
succ: Node lone -> Time
}
But this also changes all of your predicates. You can't say that a node is isolated or terminal, you can only say that a node is isolated at time T.
If you have Software Abstractions, this is all covered in section 6.1. I'm not familiar with any good guides to modeling time in Alloy outside of that book.
I'm using Alloy* hola-0.2.jar to represent and study higher-order problems.
The following code
check isAR for 1 but exactly 1 Node, exactly 1 Edge should fail with only one counterexample.
Yes, Alloy* finds the counterexample quickly. However, when I click "Next" to try to find another counterexample, the solver never finish it. (I run this for at least 3 hours in my macbook pro.)
Indeed, by theory, no more counterexample exists. So Alloy* should state No counterexample found. Assertion may be valid. But, it never pop up.
I'm aware that solving higher-order problems requires more computational effort. However this problem of mine is very small. So I doubt my code. What's the problem?
// a Heyting Algebra of subgraphs of a given graph
sig Node {}
sig Edge {
source: Node,
target: Node}
fun Edge.proj : set Node { this.source + this.target}
pred isGraph[ns: set Node, es: set Edge] {es.proj in ns}
// Cmpl[sns,ses,cns,ces] means: a pseudo-complement of a subgraph s is a subgraph c.
pred Cmpl[sns: set Node, ses: set Edge, cns: set Node, ces: set Edge] {
!((cns!=none or ces!=none) and Node in sns and Edge in ses)
Node in sns + cns
Edge in ses + ces
all ns: set Node | all es: set Edge when isGraph[ns,es] and (Node in sns + ns) and (Edge in ses + es)|
(cns in ns and ces in es)
}
/* An element x of a Heyting algebra H is called regular
* if x = ¬y for some y in H.
*/
pred isRegular [xns: set Node, xes: set Edge] {
some yns: set Node | some yes: set Edge when isGraph[yns,yes]|
one cyns: set Node | one cyes: set Edge |
isGraph[cyns,cyes] and Cmpl[yns,yes,cyns,cyes] and (cyns=xns and cyes=xes)
}
assert isAR { // is always regular?
all subns: set Node, subes: set Edge when isGraph[subns,subes] |
isRegular[subns,subes]
}
check isAR for 1 but exactly 1 Node, exactly 1 Edge
// this should fail with 1 couterexample (by theory)
For an university project I'm trying to write the chinese game of Go (http://en.wikipedia.org/wiki/Go_%28game%29) in Alloy. (i'm using the 4.2 version)
I managed to write the base structure. Go's played on a board 9 x 9 wide, but i'm using a smaller set of 3 x 3 for checking it faster.
The board is made of crosses which can either be empty or occupied by black or white stones.
abstract sig Colour {}
one sig White, Black, Empty extends Colour {}
abstract sig Cross {
Status: one Colour,
near: some Cross,
group: lone Group
}
one sig C11, C12, C13,
C21, C22, C23,
C31, C32, C33 extends Cross {}
sig Group {
stones : some Cross,
freedom : some Cross
}
pred closeStones {
near=
C11->C12 + C11->C21 +
C12->C11 + C12->C13 + C12->C22 +
C13->C12 + C13->C23 +
C21->C22 + C21->C11 + C21->C31 +
C22->C21 + C22->C23 + C22->C12 + C22->C32 +
C23->C22 + C23->C13 + C23->C33 +
C31->C32 + C31->C21 +
C32->C31 + C32->C33 + C32->C22 +
C33->C32 + C33->C23
}
fact stones2 {
all g : Group |
all c : Cross |
(c.group=g) iff c in g.stones
}
fact noGroup{
all c : Cross | (c.Status=Empty) iff c.group=none
}
fact groupNearStones {
all disj c,d : Cross |
((d in c.near) and c.Status=d.Status)
iff
d.group=c.group
}
The problem is: following Go rules, every stones must be considered as part of a group. This group is made of all the adiacent stones with the same colour.
My fact "groupNearStones" should be sufficient to describe that condition, but this way I can't get groups made of more of 3 stones.
I've tried rewriting it in different ways, but either the analizer says it found "0 variables" or it groups up all the stones with the same status, regardless of wheter they're near each other or not.
If you could give me any insight I will be grateful, since i'm breaking my head on this simple matter for days.
Ask yourself two questions.
First: in Go, what constitutes a group? You say yourself: it is a set of adjacent stones with the same color. Not that every stone in the group must be adjacent to every other; it suffices for every stone to be adjacent to another stone in the group.
So from a formal point of view: given a stone S, the set of stones in the group as S is the transitive closure of the stones reachable through the relation same_color_and_adjacent, or S.*same_color_and_adjacent.
Second: what constitutes being the same color and adjacent? I think you can define this easily, with what you have.
On a side issue; you may find it easier to scale the model to arbitrary sizes of boards if you reify the notion of rows and columns.
I hope this helps.
[Addendum:] Apparently it doesn't help enough. I'll try to be a bit more explicit, but I want the full solution to come from you and not from me.
Note that the point of defining a relation like same_color_and_adjacent is not to eliminate the formulation of facts or predicates in your model, but to make them easier to write and to write correctly. It's not magic.
Consider first a reformulation of your fact groupNearStones in terms of a single relation that holds for pairs of stones which are adjacent and have the same color. The relation can be defined by modifying your declaration for Cross:
abstract sig Cross {
Status: one Colour,
near: some Cross,
group: lone Group,
near_and_similar : some Cross
}{
near_and_similar = near & { c : Cross | c.#Status = Status}
}
Now your existing fact can be written as:
fact groupNearStones2 {
all disj c,d : Cross |
d in c.near_and_similar
iff
d.group=c.group
}
Actually, I would write both versions of groupNearStones as predicates, not facts. That would allow you to check that the new formulation is really equivalent to the old one by running a check like:
pred GNS_equal_GNS2 {
groupNearStones iff groupNearStones2
}
(I have not run such a check; I'm being a little lazy.)
Now, let us consider the problems you mention:
You never get groups containing more than three stones. Actually, given the formulation of groupNearStones, I'm surprised you get groups with more than two. Consider what groupNearStones says: any two stones in a group are adjacent and have the same color. Draw a board on a piece of paper and draw a group of five stones. Now ask whether such a group satisfies the fact groupNearStones. Say the group is C11, C12, C13, C21, C22. What does groupNearStones say about the pair C21, C13?
Do you see the problem? Are the relations near and 'close enough to be in the same group' really the same? If they are not the same, are they related?
Hint: think about transitive closure.
You never get groups containing a single stone.
How surprising is this, given that groupNearStones says that c.group = d.group only if c and d are disjoint? If you never get single-stone groups, then every stone that should be a single-stone group is not classed as being in any group at all, since such a stone must not satisfy the expression s.group = s.group.
Do you see the problem?
Hint: think about reflexive transitive closure.
Is it possible to model random failures in Alloy?
For instance, I currently have a connected graph that is passing data at various time steps to its neighbors. What I am trying to do is figure out some method for allowing the model to randomly kill links, and in doing so, still manage to fulfill its goal (of ensuring that all nodes have had their data state set to On).
open util/ordering[Time]
enum Datum{Off, On} // A simple representation of the state of each node
sig Time{state:Node->one Datum} // at each time we have a network state
abstract sig Node{
neighbours:set Node
}
fact {
neighbours = ~neighbours -- symmetric
no iden & neighbours -- no loops
all n : Node | Node in n.*neighbours -- connected
-- all n : Node | (Node - n) in n.neighbours -- comp. connected
}
fact start{// At the start exactly one node has the datum
one n:Node|first.state[n]=On
}
fact simple_change{ // in one time step all neighbours of On nodes become on
all t:Time-last |
let t_on = t.state.On |
next[t].state.On = t_on+t_on.neighbours
}
run {} for 5 Time, 10 Node
The software I'm attempting to model deals in uncertainty. Basically, links between nodes can fail, and the software reroutes along another path. What I'd like to try to do in Alloy is to have some facility for links to 'die' at certain timesteps (preferably randomly). In the top-most fact, I have the capability for the graph to be completely connected, so its possible that, if a link dies, another can possibly pick up the slack (as the simple_change switches the state of the Datum to be On for all connected neighbors).
Edit:
So, I did as was suggested and ran into the following error:
I am confused, as I thought neighbours and Node were still sets?
Here is my updated code:
open util/ordering[Time]
open util/relation
enum Datum{Off, On} // A simple representation of the state of each node
sig Time{
neighbours : Node->Node,
state:Node->one Datum // at each time we have a network state
}{
symmetric[neighbours, Node]
}
abstract sig Node{
neighbours:set Node
}
fact {
neighbours = ~neighbours -- symmetric
no iden & neighbours -- no loops
-- all n : Node | (Node - n) in n.neighbours -- comp. connected
all n : Node | Node in n.*neighbours -- connected
}
// At the start exactly one node has the datum
fact start{
one n:Node|first.state[n]=On
}
// in one time step all neighbours of On nodes become on
fact simple_change{
all t:Time-last |
let t_on = t.state.On |
next[t].state.On = t_on+t_on.neighbours
all t:Time-last | next[t].neighbours in t.neighbours
all t:Time-last | lone t.neighbours - next[t].neighbours
}
run {} for 10 Time, 3 Node
Move the definition of neighbours into Time:
sig Time {neighbours : Node->Node, ....}
You will need to re-express the facts about symmetry etc of neighbours relative to each time point. This is most easily done by doing it in the invariant part of the Time signature:
sig Time {
neighbours : Node->Node,
...
}{
symmetric[neighbours, Node],
....
}
(I do recommend the use of open util/relation to load useful definitions such as symmetric.)
Then the time step simple_change can be complicated by adding in a fact such as
next[t].neighbours in t.neighbours
which can throw away arbitrarily many arcs.
If you want to restrict how many arcs are thrown away in each step you can add a further fact such as
lone t.neighbours - next[t].neighbours
which restricts disposal to at most one arc.
Can someone please help me understand predicates using the following example:
sig Light{}
sig LightState { color: Light -> one Color}
sig Junction {lights: set Light}
fun redLigths(s:LightState) : set Light{ s.color.Red}
pred mostlyRed(s:LightState, j:Junction){
lone j.lights - redLigths(s)
}
I have the below questions about the above code:
1) What happens if the above predicate is true?
2) What happends if it is false?
3) Can someone show me a bit of alloy code that uses the above code and clarifies the meaning of predicates through the code.
I am just trying to understand how do we use the above predicate.
Nothing "happens" until you place a call to a predicate or a function in a command to find an example or counterexample.
First, use the right terminology, nothing 'happens' when a predicate is true; it's the more like the other way around, an instance (an allocation of atoms to sets) satisfies (or doesn't) some condition, making the predicate true (or false).
Also, your model is incomplete, because there is no sig declaration for Color (which should include an attribute called Red).
I assume you want to model a world with crossroads containing traffic lights, if so I would use the following model:
abstract sig Color {}
one sig Red,Yellow,Green extends Color {}
sig Light {
color: Color
}
sig Junction {
lights : set Light
}
// This is just for realism, make sure each light belongs to exactly one junction
fact {
Light = Junction.lights
no x,y:Junction | x!=y and some x.lights & y.lights
}
fun count[j:Junction, c:Color] : Int {
#{x:Light | x in j.lights and x.color=c}
}
pred mostly[j:Junction, c:Color] {
no cc:Color | cc!=c and count[j,cc]>=count[j,c]
}
run{
some j:Junction | mostly[j,Red]
} for 10 Light, 2 Junction, 10 int
Looking at the above, i'm using the # operator to count the number of atoms in a set, and I'm specifying a bitwidth of 10 to integers just so that I don't stumble into an overflow when using the # operator for large sets.
When you execute this, you will get an instance with at least one junction that has mostly red lights, it will be marked as $j in the visualizer.
Hope this helps.
sig Light{}
sig LightState { color: Light -> one Color}
sig Junction {lights: set Light}
fun redLigths(s:LightState) : set Light{ s.color.Red}
pred mostlyRed(s:LightState, j:Junction){
lone j.lights - redLigths(s)
}
What the predicate simply means in the example you gave is;
The difference between the set A, in this case the relation (j.lights) and another set say B, returned from the function redligths, of which the Predicate will always constraint the constraint analyser to return only red light when you run the Predicate "mostlyRed".
And note that the multiplicity "lone" you added to the predicate's body only evaluate after the difference between the set A and B (as I assumed) has been evaluated, to make sure that at most one atom of red is returned. I hope my explanation was helpful. I will welcome positive criticism. Thanks