Alloyチュートリアル (1) Alloyの基本的な使い方

グラフを構築する

このワークショップでは、Alloy を使用してグラフをモデル化します。数学的には、グラフは単に ⟨V, E⟩ のペアであることを思い出してください。ここで、V は頂点のセット (別名ノード)、E はエッジのセットです。E の各メンバーはペア (v, u) 1 であり、v と u のそれぞれは V からの頂点です。(v, u) は、グラフに頂点 v から頂点 u までのエッジがある場合にのみ E に含まれます。
次の署名宣言を使用して、Alloy でこれをモデル化します。
ここに画像の説明を挿入

最初の部分では、グラフ内の可能なノードのセットとなるノードのセットを宣言します。2 番目の部分では、
ノード上のバイナリ関係エッジを宣言します。技術的には、「1 つの」要素だけを持つグラフのセット Graph を宣言します
(つまり、私たちのモデルは 1 つのグラフだけについて話しています)。
任意のグラフ g について、g.edges はそのグラフのエッジ関係になります。
セット Graph には 1 つの要素しか含まれていないため、モデル内のグラフ内のエッジのセットを参照するには、単に Graph.edges を記述するだけです。

述語

次の述語定義を入力します。これは、グラフ g に正確に 2 つのエッジがある場合を指定します。
ここに画像の説明を挿入

  • 述語の機能は単純です。与えられたグラフ インスタンスで、グラフが述語の定義を満たす場合、述語はhold、またはpred結果は です。true

    run コマンドを使用すると、この述語の満足のいくインスタンスを表示できます。つまり、Alloy に
    正確に 2 つのエッジを持つグラフを表示させることができます。次の実行コマンドを追加し、
    メニューから [実行] → [実行には 2 つのエッジがあります] を選択します。

無向無向グラフ

グラフが無向である場合にグラフ g に当てはまる述語 is undirected を記述します。
無向グラフとは、エッジ (v, u) を含む場合は必ず対称エッジ (u, v) も含むグラフであることを思い出してください。
run コマンドを使用して、述語のインスタンスを表示します。

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] )
}
  • 間違った表現に注意してください。

    pred is_undirected[g: Graph]{
          
          
    // 错误写法:
    // all u, v : Node | (g.edges[u] <=> g.edges[v])
    // 因为 g.edges[u] 返回的不是布尔类型
    }
    
  • g.edges[u]返されるものはboolまったく型ではないため、<=>そのような論理シンボルを連結するのは明らかに間違っています

undirected2 無向グラフを作成する 2 番目の方法

次の 2 つの関数はそれぞれ、グラフ g とノード v が与えられると、v へのエッジを持つノードのセットと v からのエッジを持つノードのセットを返す短縮関数です。
ここに画像の説明を挿入
これらの関数を使用して、グラフ g が無向の場合に正確に保持される述語 is undirected2 を作成します


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

主張する

次のアサーションは、2 つの定義 is undirected と is undirected2 が論理的に同等であることを主張します。
ここに画像の説明を挿入
ここに画像の説明を挿入

ここでは、各シグネチャの最大 20 メンバーのサイズのモード、つまり最大 20 のノードを持つグラフをチェックするように Alloy に指示しています。このコマンドを入力し、メニューから「実行」→「20 に相当する無指向性チェック」を選択してチェックを実行します。Alloy は反例 (つまり、このアサーションが false であるモデル) を見つけてはならず、次のような出力を生成する必要があります。
ここに画像の説明を挿入

事実

Alloy ファクト宣言は公理、つまり Alloy が想定する仮定が常に真であることを宣言します。モデルのインスタンスを生成するとき、またはアサーションに対する反例を検索するとき、Alloy はファクト宣言に記載されている仮定を満たすもののみを考慮します。

ここに画像の説明を挿入

この事実は何を物語っているでしょうか? この事実を変更して、すべてのグラフには正確に 3 つのエッジがあると表現します。次に、has twoedges 述語を再実行します。何が起こるのですか?なぜ?

  • ファクトの意味は、fact定義を満たす条件のみを強制的に考慮し、満たさないその他の条件は自動的にフィルタリングすることです。
fact at_least_one_edge{
    
    
	all g:Graph | #g.edges=3
}

pred hasTwoEdges[g: Graph]{
    
    
	#g.edges = 2
}
run hasTwoEdges
  • ここではrun一致する要件が見つからないはずですinstance
  • runすべての がinstance3 つあると想定されているためedge、のインスタンスがhasTwoEdgeちょうど 2 つある限りedge、適格なインスタンスは存在しません。

拡大

時間があれば、次の述語は何を意味しますか? それぞれを入力し、Alloy の run コマンドを使用すると、論理的に何を言っているのか理解できます。答えを Alloy ファイルのコメントとして書き留めます。
ここに画像の説明を挿入

どちらの pred 定義もグラフ内の何らかの関係を記述しようとしていますが、その意味は異なります。

  • what_does_this_mean1[g: Graph]:この述語は、グラフ g において、すべてのノード u および v に対して、u から v へのエッジと、v から u へのエッジが存在することを意味します。無向グラフの特性として、u から v へのエッジがある場合、v から u へのエッジが必ず存在するため、この述語は実際には無向グラフを記述しています。

  • what_does_this_mean2[g: Graph]:この述語は、グラフ g において、すべてのノード u および v について、u から v へのエッジ、v から u へのエッジ、またはその両方が存在することを意味します。この述語の意味はより広く、実際には接続されたグラフを表します。接続されたグラフの特徴は、ノードのすべてのペアについて、2 つのノードを接続するエッジが少なくとも 1 つあることです。u から v へのエッジがある場合、v から u へのエッジが存在する必要はないため、これはグラフが無向であることを意味するものではないことに注意してください。

  • what_does_this_mean1[g: Graph]しかし、 とis_undirectedが同等であると考えたところis_undirected2、そうではないことがわかりました。


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 
  • 上記のコードでそれを見つけましたcounter example。シナリオは次のとおりです。

ノード1 -> ノード1
ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/qq_42902997/article/details/131154266