Alloy Tutorial (1) Basic use of Alloy

construct a graph

In this workshop we are going to use Alloy to model graphs. Mathematically, recall that a graph is just a pair ⟨V, E⟩ where V is a set of vertices (aka nodes) and E is a set of edges. Each member of E is a pair (v, u) 1 where each of v and u are vertices from V . (v, u) is in E if and only if the graph has an edge from vertex v to vertex u.
We will model this in Alloy using the following signature declaration.
insert image description here

The first part declares a set Node which will be the set of possible nodes in the graph. The second part
declares a binary relation edges on Nodes. Technically it declares a set Graph of graphs that has only
“one” element (i.e. our model is talking about just a single graph). For any graph g, g.edges is then the
edge relation for that graph. Since the set Graph has only one element in it, to refer to the set of edges in
the graph in our model we can just write Graph.edges.

predicate

Enter the following predicate definition, which specifies when a graph g has exactly two edges.
insert image description here

  • The function of the predicate is simple: given a graph instance, when the graph satisfies the definition of the predicate, the predicate is hold, or predthe result istrue

    We can use the run command to view satisfying instances of this predicate, i.e. to get Alloy to show us
    graphs that have exactly two edges. Add the following run command and then choose Execute → Run
    has two edges from the menu.

undirected undirected graph

Write a predicate is undirected that holds for a graph g when that graph is undirected. Recall an
undirected graph is one such that whenever it contains an edge (v, u) it also contains the symmetric edge (u, v).
Use the run command to view instances of your predicate.

sig Node{
    
    }

one sig Graph{
    
    
	edges: Node -> Node
}

//
//pred hasTwoEdges{
    
    
//	all g: Graph | #g.edges = 2
//}

pred hasTwoEdges[g: Graph]{
    
    
	#g.edges = 2
}

pred is_undirected[g: Graph]{
    
    
// 错误写法:
// all u, v : Node | (g.edges[u] <=> g.edges[v])
// 因为 g.edges[u] 返回的不是布尔类型
//	all u, v : Node | (v in g.edges[u] <=> u in g.edges[v])
	all u, v : Node | (v in g.edges[u] => u in g.edges[v] and u in g.edges[v] =>v in g.edges[u] )
}
  • Be sure to pay attention to the wrong wording:

    pred is_undirected[g: Graph]{
          
          
    // 错误写法:
    // all u, v : Node | (g.edges[u] <=> g.edges[v])
    // 因为 g.edges[u] 返回的不是布尔类型
    }
    
  • g.edges[u]What is returned is not boolof type at all, so <=>it is definitely wrong to concatenate with such logical symbols

undirected2 The second way to write an undirected graph

The following two functions are shorthand respectively that given a graph g and node v, return the set of nodes with edges to v, and those with edges from v respectively.
insert image description here
Using these functions, write a predicate is undirected2 that holds for a graph g precisely when g is
undirected.


fun edges_to[g: Graph, v: Node]: set Node {
    
    
	//given a graph g and node v, return the set of nodes with edges to v,
	g.edges.v
}

fun edges_from[g: Graph, v: Node]: set Node {
    
    
	//given a graph g and node v, return the set of nodes with edges from v,
	g.edges[v]
}

pred is_undirected2[g:Graph]{
    
    
	all u: Node | edges_to[g, u] = edges_from[g, u]
}

run is_undirected2 for 3 but 5 Node

assert

The following assertion asserts that the two definitions is undirected and is undirected2 are logically equivalent.
insert image description here
insert image description here

Here we are instructing Alloy to check it for modes of size up to 20 members of each signature, i.e. graphs that have at most 20 nodes. Enter this command and then execute the check by choosing Execute → Check is undirected equiv for 20 from the menu. Alloy should not find any counter-example (i.e. any model in which this assertion is false), and should produce output like the following:
insert image description here

Fact

Alloy fact declarations declare axioms, i.e. assumptions that Alloy will assume are always true. When generating instances of a model or searching for counter-examples to an assertion, Alloy will only consider ones that satisfy the assumptions stated in fact declarations.

insert image description here

What does this fact say? Modify this fact to instead say that every graph has exactly three (3) edges. Then re-run the has two edges predicate. What happens? Why?

  • The meaning of fact is to force only factthe conditions that meet the definition to be considered, and others that do not meet are automatically filtered
fact at_least_one_edge{
    
    
	all g:Graph | #g.edges=3
}

pred hasTwoEdges[g: Graph]{
    
    
	#g.edges = 2
}
run hasTwoEdges
  • runYou must not find any matching requirements hereinstance
  • Because it is assumed that there are 3 runof all , but as long as there are exactly 2 instances of , there is no eligible instanceinstanceedgehasTwoEdgeedge

expand

If you have time: What do the following predicates mean? Enter each and use Alloy’s run command to help work out what they are saying logically. Write down your answer as comments in your Alloy file.
insert image description here

Both pred definitions attempt to describe some relationship in the graph, but their meanings are different:

  • what_does_this_mean1[g: Graph]: This predicate means that in graph g, for all nodes u and v, there exists an edge from u to v, and an edge from v to u. This predicate is actually describing an undirected graph, because the property of an undirected graph is that if there is an edge from u to v, then there must be an edge from v to u.

  • what_does_this_mean2[g: Graph]: This predicate means that in graph g, for all nodes u and v, there exists either an edge from u to v, an edge from v to u, or both. The meaning of this predicate is broader. It actually describes a connected graph. The characteristic of a connected graph is that for all pairs of nodes, there is at least one edge that makes the two nodes connected. Note that this does not mean that the graph is undirected, since it does not require that if there is an edge from u to v, then there must be an edge from v to u.

  • But when I thought what_does_this_mean1[g: Graph]that and is_undirectedand is_undirected2were equivalent, I found that it was not:


pred what_does_this_mean1[g: Graph] {
    
    
all u, v: Node | (u -> v) in g.edges and (v -> u) in g.edges
}
pred what_does_this_mean2[g: Graph] {
    
    
all u, v: Node | (u -> v) in g.edges or (v -> u) in g.edges
}

assert isEqual{
    
    
	all g:Graph | what_does_this_mean1[g] <=> is_undirected2[g]
}

//run hasTwoEdges
//check is_undirected_equiv for 20

check isEqual 
  • I found it in the above code counter example, the scenario is:

Node1 -> Node1
insert image description here

Guess you like

Origin blog.csdn.net/qq_42902997/article/details/131154266