|
| 1 | +open util/ordering[Time] |
| 2 | + |
| 3 | +sig Time {} |
| 4 | +//sig Cost {} |
| 5 | + |
| 6 | + |
| 7 | +//----------------------------------------------------------------------------- |
| 8 | +// ネットワーク構造の定義 |
| 9 | +//----------------------------------------------------------------------------- |
| 10 | + |
| 11 | +sig Node { |
| 12 | + link : set Node, |
| 13 | + pathCost : Int -> Time, |
| 14 | + upstream : Node -> Time, |
| 15 | +} |
| 16 | + |
| 17 | +one sig Root extends Node {} |
| 18 | + |
| 19 | +fact topology { |
| 20 | + // ノードaからノードbにリンクが存在するならば、bからaにリンクが存在する |
| 21 | + all a, b : Node | (a -> b in link) implies (b -> a in link) |
| 22 | + |
| 23 | + // 自分自身へのリンクは存在しない |
| 24 | + all n : Node | n -> n not in link |
| 25 | + |
| 26 | + // 連結である ⇔ 任意のノード間にパスが存在する |
| 27 | + all a, b : Node | b in a.*link |
| 28 | +} |
| 29 | + |
| 30 | +fact pathCostProperty { |
| 31 | + // pathCost は unique |
| 32 | + all n : Node, t : Time | one n.pathCost.t |
| 33 | + |
| 34 | + // Root の pathCost はゼロ |
| 35 | + all t : Time | Root.pathCost.t = 0 |
| 36 | +} |
| 37 | + |
| 38 | +fact upstreamProperty { |
| 39 | + // upstream はたかだか一つ |
| 40 | + all n : Node, t : Time | lone n.upstream.t |
| 41 | + |
| 42 | + // upstream が存在しないのは Root に限る |
| 43 | + all n : Node, t : Time | no n.upstream.t iff n = Root |
| 44 | + |
| 45 | + // upstream は link されているものに限る |
| 46 | + all n : Node, t : Time | n.upstream.t in n.link |
| 47 | +} |
| 48 | + |
| 49 | +fact init { |
| 50 | + // 初期状態では pathCost はゼロとする |
| 51 | + all n : Node | n.pathCost.first = 0 |
| 52 | +} |
| 53 | + |
| 54 | +//----------------------------------------------------------------------------- |
| 55 | +// ネットワークの時間発展に関する述語の定義 |
| 56 | +//----------------------------------------------------------------------------- |
| 57 | + |
| 58 | +// そのノードに時間経過による変化が生じないこと |
| 59 | +pred unchanged(n : Node, t, t' : Time) { |
| 60 | + n.pathCost.t = n.pathCost.t' |
| 61 | + n.upstream.t = n.upstream.t' |
| 62 | +} |
| 63 | + |
| 64 | +// そのノード自身から見て情報更新の必要がないこと |
| 65 | +pred locallyStable(n : Node, t, t' : Time) { |
| 66 | + // upstream が隣接するノードの中で最もパスコストが低いノードである |
| 67 | + all neigh : n.link | (n.upstream.t').(pathCost.t) <= neigh.pathCost.t |
| 68 | + |
| 69 | + // 自身の pathCost が upstream の pathCost に1を加えた値である |
| 70 | + n.pathCost.t' = plus[(n.upstream.t').(pathCost.t), 1] |
| 71 | +} |
| 72 | + |
| 73 | +// どのノードも情報更新の必要がなくアルゴリズムが収束した |
| 74 | +pred converged(t : Time) { |
| 75 | + all n : Node | n = Root or locallyStable[n, t, t.next] |
| 76 | +} |
| 77 | + |
| 78 | + |
| 79 | +//----------------------------------------------------------------------------- |
| 80 | +// イベントの定義 |
| 81 | +//----------------------------------------------------------------------------- |
| 82 | + |
| 83 | +abstract sig Event { |
| 84 | + pre : one Time, |
| 85 | + post : one Time, |
| 86 | +} |
| 87 | + |
| 88 | +fact trace { |
| 89 | + // pre の次の時刻が post である |
| 90 | + all e : Event | e.post = e.pre.next |
| 91 | + |
| 92 | + // 最後以外の任意の時刻において、その時刻に発生するイベントが存在する |
| 93 | + all t : Time - last | one pre.t |
| 94 | +} |
| 95 | + |
| 96 | +sig Skip extends Event {} { |
| 97 | + // (事前条件) Learn できるノードがない ⇔ 収束している |
| 98 | + // 簡単のため、無駄な Skip が途中に挟まらないようにしておく |
| 99 | + converged[pre] |
| 100 | + |
| 101 | + // (事後条件) すべてのノードが変化なし |
| 102 | + all n : Node | unchanged[n, pre, post] |
| 103 | +} |
| 104 | + |
| 105 | +sig Learn extends Event { |
| 106 | + learner : one Node |
| 107 | +} { |
| 108 | + // (事前条件) Root は Learn できない |
| 109 | + learner != Root |
| 110 | + |
| 111 | + // (事前条件) 既に stable なノードは Learn できない |
| 112 | + // この条件は必須ではないが、わかりやすさのため |
| 113 | + not locallyStable[learner, pre, pre] |
| 114 | + |
| 115 | + // (事後条件) learner が stable な状態に遷移する |
| 116 | + locallyStable[learner, pre, post] |
| 117 | + |
| 118 | + // (事後条件) learner 以外は変化しない |
| 119 | + all n : Node - learner | unchanged[n, pre, post] |
| 120 | +} |
| 121 | + |
| 122 | + |
| 123 | +//----------------------------------------------------------------------------- |
| 124 | +// 性質の検査 |
| 125 | +//----------------------------------------------------------------------------- |
| 126 | + |
| 127 | +// いつか収束する |
| 128 | +assert eventuallyConverged { |
| 129 | + some t : Time | converged[t] |
| 130 | +} |
| 131 | + |
| 132 | +check eventuallyConverged for 7 but 4 Node |
| 133 | + |
| 134 | + |
| 135 | +pred spanningTree(t : Time) { |
| 136 | + // 辺の数が頂点数-1であるため、連結であれば木と言える |
| 137 | + Root.*~(upstream.t) = Node |
| 138 | +} |
| 139 | + |
| 140 | +// 収束した場合、全域木が得られている |
| 141 | +assert convergesToSpanningTree { |
| 142 | + all t : Time | converged[t] implies spanningTree[t] |
| 143 | +} |
| 144 | + |
| 145 | +check convergesToSpanningTree for 7 but 4 Node |
| 146 | + |
| 147 | + |
| 148 | + |
| 149 | + |
| 150 | + |
| 151 | + |
| 152 | + |
| 153 | + |
| 154 | + |
| 155 | + |
| 156 | + |
0 commit comments