Guest User

Untitled

a guest
Feb 24th, 2018
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 24.67 KB | None | 0 0
  1. theory EWD840
  2. imports "HOL-TLA.TLA"
  3. begin
  4.  
  5. section Utilities
  6.  
  7. text ‹A handful of general lemmas that were useful along the way.›
  8.  
  9. lemma temp_impI:
  10. assumes "sigma ⊨ P ⟹ sigma ⊨ Q"
  11. shows "sigma ⊨ P ⟶ Q"
  12. using assms by simp
  13.  
  14. lemma imp_leadsto_reflexive: "⊢ S ⟶ (F ↝ F)" using LatticeReflexivity [where F = F] by auto
  15.  
  16. lemma imp_leadsto_transitive:
  17. assumes "⊢ S ⟶ (F ↝ G)" "⊢ S ⟶ (G ↝ H)"
  18. shows "⊢ S ⟶ (F ↝ H)"
  19. proof (intro tempI temp_impI)
  20. fix sigma
  21. assume S: "S sigma"
  22. with assms have 1: "sigma ⊨ (F ↝ G)" "sigma ⊨ (G ↝ H)"
  23. by (auto simp add: Valid_def)
  24.  
  25. from 1 LatticeTransitivity [where F = F and G = G and H = H]
  26. show "sigma ⊨ F ↝ H"
  27. by (auto simp add: Valid_def)
  28. qed
  29.  
  30. lemma imp_leadsto_diamond:
  31. assumes "⊢ S ⟶ (A ↝ (B ∨ C))"
  32. assumes "⊢ S ⟶ (B ↝ D)"
  33. assumes "⊢ S ⟶ (C ↝ D)"
  34. shows "⊢ S ⟶ (A ↝ D)"
  35. proof (intro tempI temp_impI)
  36. fix sigma
  37. assume S: "sigma ⊨ S"
  38. with assms have
  39. ABC: "sigma ⊨ A ↝ (B ∨ C)" and
  40. BD: "sigma ⊨ B ↝ D" and
  41. CD: "sigma ⊨ C ↝ D"
  42. by (auto simp add: Valid_def)
  43. with LatticeDiamond [where A = A and B = B and C = C and D = D]
  44. show "sigma ⊨ A ↝ D"
  45. by (auto simp add: Valid_def)
  46. qed
  47.  
  48. lemma temp_conj_eq_imp:
  49. assumes "⊢ P ⟶ (Q = R)"
  50. shows "⊢ (P ∧ Q) = (P ∧ R)"
  51. using assms by (auto simp add: Valid_def)
  52.  
  53. text ‹The following lemma is particularly useful for a system that makes
  54. some progress which either reaches the desired state directly or which leaves it in
  55. a state that is definitely not the desired state but from which it can reach the desired state via
  56. some further progress.›
  57.  
  58. lemma imp_leadsto_triangle_excl:
  59. assumes AB: "⊢ S ⟶ (A ↝ B)"
  60. assumes BC: "⊢ S ⟶ ((B ∧ ¬C) ↝ C)"
  61. shows "⊢ S ⟶ (A ↝ C)"
  62. proof -
  63. have "⊢ ((B ∧ ¬C) ∨ (B ∧ C)) = B" by auto
  64. from inteq_reflection [OF this] AB have ABCBC: "⊢ S ⟶ (A ↝ ((B ∧ ¬C) ∨ (B ∧ C)))" by simp
  65.  
  66. show ?thesis
  67. proof (intro imp_leadsto_diamond [OF ABCBC] BC)
  68. from ImplLeadsto_simple [where F = "LIFT (B ∧ C)"]
  69. show "⊢ S ⟶ (B ∧ C ↝ C)"
  70. by (auto simp add: Valid_def)
  71. qed
  72. qed
  73.  
  74. text ‹An action that updates a single value of a function.›
  75.  
  76. definition updatedFun :: "('a ⇒ 'b) stfun ⇒ 'a ⇒ 'b trfun ⇒ action" where
  77. "updatedFun f x v ≡ ACT (∀n. id<f$,#n> = (if #n = #x then v else id<$f,#n>))"
  78.  
  79. section Nodes
  80.  
  81. text ‹There is a fixed, finite, set of nodes, which are numbered. Introduce a distinct type
  82. for node identifiers, and an ordering relation, and an induction principle.›
  83.  
  84. axiomatization NodeCount :: nat where NodeCount_positive: "NodeCount > 0"
  85.  
  86. typedef Node = "{0..<NodeCount}" using NodeCount_positive by auto
  87.  
  88. definition FirstNode :: Node where "FirstNode == Abs_Node 0"
  89. definition LastNode :: Node where "LastNode == Abs_Node (NodeCount-1)"
  90. definition PreviousNode :: "Node ⇒ Node" where "PreviousNode == λn. Abs_Node (Rep_Node n - 1)"
  91.  
  92. instantiation Node :: linorder
  93. begin
  94. definition less_eq_Node :: "Node ⇒ Node ⇒ bool" where "n ≤ m ≡ Rep_Node n ≤ Rep_Node m"
  95. definition less_Node :: "Node ⇒ Node ⇒ bool" where "n < m ≡ Rep_Node n < Rep_Node m"
  96.  
  97. instance proof
  98. show "⋀(x::Node) y. (x < y) = (x ≤ y ∧ ¬ y ≤ x)" using less_Node_def less_eq_Node_def by force
  99. show "⋀(x::Node). x ≤ x" using less_eq_Node_def by force
  100. show "⋀(x::Node) y z. x ≤ y ⟹ y ≤ z ⟹ x ≤ z" using less_eq_Node_def by force
  101. show "⋀(x::Node) y. x ≤ y ∨ y ≤ x" using less_eq_Node_def by force
  102. show "⋀(x::Node) y. x ≤ y ⟹ y ≤ x ⟹ x = y" using less_Node_def less_eq_Node_def
  103. by (simp add: Rep_Node_inject)
  104. qed
  105. end
  106.  
  107. lemma PreviousNode_fixed_point:
  108. assumes "n = PreviousNode n"
  109. shows "n = FirstNode"
  110. using assms
  111. unfolding PreviousNode_def FirstNode_def
  112. by (metis Abs_Node_inject One_nat_def Rep_Node Rep_Node_inverse atLeastLessThan_iff cancel_comm_monoid_add_class.diff_cancel diff_Suc_less diff_le_self le_less_trans le_neq_implies_less not_le)
  113.  
  114. lemma Node_gt_PreviousNode:
  115. assumes "n ≠ FirstNode"
  116. shows "m > (PreviousNode n) = (m > n ∨ m = n)"
  117. using assms unfolding PreviousNode_def less_Node_def FirstNode_def
  118. by (smt Abs_Node_inverse Rep_Node Rep_Node_inject atLeastLessThan_iff diff_Suc_1 diff_is_0_eq' diff_le_self le_add_diff_inverse less_Suc_eq_le not_le_imp_less not_less_iff_gr_or_eq)
  119.  
  120. lemma Node_gt_ne: "(m::Node) > n ⟹ m ≠ n" unfolding less_Node_def by blast
  121.  
  122. lemma Node_gt_LastNode [simp]: "n > LastNode = False"
  123. unfolding LastNode_def less_Node_def
  124. using Abs_Node_inverse NodeCount_positive Rep_Node not_less_eq by auto
  125.  
  126. lemma Node_induct [case_names FirstNode PreviousNode]:
  127. assumes FirstNode: "P FirstNode"
  128. assumes PreviousNode: "⋀n. n ≠ FirstNode ⟹ P (PreviousNode n) ⟹ P n"
  129. shows "P n"
  130. proof -
  131. define n_num where "n_num == Rep_Node n"
  132. have n_eq: "n = Abs_Node n_num"
  133. by (simp add: Rep_Node_inverse n_num_def)
  134.  
  135. have "n_num < NodeCount" using Rep_Node n_num_def by auto
  136. thus ?thesis
  137. unfolding n_eq
  138. proof (induct n_num)
  139. case 0 with FirstNode show ?case by (simp add: FirstNode_def)
  140. next
  141. case (Suc n_num)
  142. hence hyp: "P (Abs_Node n_num)" by auto
  143.  
  144. show ?case
  145. proof (rule PreviousNode)
  146. show "Abs_Node (Suc n_num) ≠ FirstNode" unfolding FirstNode_def
  147. by (simp add: Abs_Node_inject NodeCount_positive Suc.prems)
  148. from hyp Suc.prems show " P (PreviousNode (Abs_Node (Suc n_num)))"
  149. unfolding PreviousNode_def by (simp add: Abs_Node_inverse)
  150. qed
  151. qed
  152. qed
  153.  
  154. datatype TerminationState = MaybeTerminated | NotTerminated
  155.  
  156. axiomatization
  157. isNodeActive :: "(Node ⇒ bool) stfun" and
  158. nodeState :: "(Node ⇒ TerminationState) stfun" and
  159. tokenPosition :: "Node stfun" and
  160. tokenState :: "TerminationState stfun"
  161. where
  162. ewd_basevars: "basevars (isNodeActive, nodeState, tokenPosition, tokenState)"
  163.  
  164. definition StartState :: stpred where
  165. "StartState == PRED tokenPosition = #FirstNode ∧ tokenState = #NotTerminated"
  166.  
  167. definition InitiateProbe :: action where
  168. "InitiateProbe == ACT
  169. (($tokenPosition = #FirstNode)
  170. ∧ ($tokenState = #NotTerminated ∨ id<$nodeState,#FirstNode> = #NotTerminated)
  171. ∧ tokenPosition$ = #LastNode
  172. ∧ tokenState$ = #MaybeTerminated
  173. ∧ (unchanged isNodeActive)
  174. ∧ (updatedFun nodeState FirstNode (const MaybeTerminated)))"
  175.  
  176. definition PassToken :: "Node ⇒ action" where
  177. "PassToken i == ACT
  178. (($tokenPosition = #i)
  179. ∧ ($tokenPosition ≠ #FirstNode)
  180. ∧ (¬ id<$isNodeActive,#i> ∨ id<$nodeState,#i> = #NotTerminated ∨ $tokenState = #NotTerminated)
  181. ∧ (tokenPosition$ = PreviousNode<$tokenPosition>)
  182. ∧ (tokenState$ = (if id<$nodeState,#i> = #NotTerminated then #NotTerminated else $tokenState))
  183. ∧ (unchanged isNodeActive)
  184. ∧ (updatedFun nodeState i (const MaybeTerminated)))"
  185.  
  186. definition SendMsg :: "Node ⇒ action" where
  187. "SendMsg i == ACT
  188. id<$isNodeActive,#i>
  189. ∧ (∃ j. #j ≠ #i ∧ (updatedFun isNodeActive j (const True))
  190. ∧ (updatedFun nodeState i (ACT if #i < #j then #NotTerminated else id<$nodeState,#i>)))
  191. ∧ unchanged (tokenPosition, tokenState)"
  192.  
  193. definition Deactivate :: "Node ⇒ action" where
  194. "Deactivate i == ACT
  195. id<$isNodeActive,#i>
  196. ∧ (updatedFun isNodeActive i (const False))
  197. ∧ unchanged (tokenPosition, tokenState, nodeState)"
  198.  
  199. definition Controlled :: action where
  200. "Controlled ≡ ACT (InitiateProbe ∨ (∃ n. PassToken n))"
  201.  
  202. definition Environment :: action where
  203. "Environment ≡ ACT (∃ n. SendMsg n ∨ Deactivate n)"
  204.  
  205. definition Next :: action where
  206. "Next ≡ ACT (Controlled ∨ Environment)"
  207.  
  208. definition Fairness :: temporal where
  209. "Fairness ≡ TEMP WF(Controlled)_(isNodeActive,nodeState,tokenPosition,tokenState)"
  210.  
  211. definition Spec :: temporal where
  212. "Spec ≡ TEMP (Init StartState ∧ □[Next]_(isNodeActive,nodeState,tokenPosition,tokenState) ∧ Fairness)"
  213.  
  214. definition TerminationDetected :: stpred where
  215. "TerminationDetected ≡ PRED
  216. (tokenPosition = #FirstNode
  217. ∧ tokenState = #MaybeTerminated
  218. ∧ id<nodeState,#FirstNode> = #MaybeTerminated
  219. ∧ ¬ id<isNodeActive,#FirstNode>)"
  220.  
  221. lemma angle_Controlled_lifted: "⊢ <Controlled>_(isNodeActive, nodeState, tokenPosition, tokenState) = Controlled"
  222. unfolding angle_def Controlled_def InitiateProbe_def PassToken_def updatedFun_def
  223. using PreviousNode_fixed_point by auto
  224.  
  225. lemmas angle_Controlled = inteq_reflection [OF angle_Controlled_lifted]
  226.  
  227. lemma basevars_arbitrary:
  228. assumes "⋀u. ⟦ tokenPosition u = A; tokenState u = B; isNodeActive u = C; nodeState u = D ⟧ ⟹ P"
  229. shows P
  230. using assms ewd_basevars unfolding basevars_def surj_def apply auto by metis
  231.  
  232. lemma enabled_controlled_lifted:
  233. "⊢ Enabled Controlled
  234. = (tokenState = #NotTerminated ∨ id<nodeState, tokenPosition> = #NotTerminated ∨ (tokenPosition ≠ #FirstNode ∧ ¬ id<isNodeActive, tokenPosition>))"
  235. proof -
  236. have 1: "⊢ Enabled Controlled = (Enabled InitiateProbe ∨ Enabled (∃n. PassToken n))"
  237. unfolding Controlled_def
  238. using enabled_disj by simp
  239.  
  240. have 2: "⊢ Enabled InitiateProbe = (tokenPosition = #FirstNode ∧ (tokenState = #NotTerminated ∨ id<nodeState, #FirstNode> = #NotTerminated))"
  241. proof (intro intI)
  242. fix w
  243. show "w ⊨ Enabled InitiateProbe = (tokenPosition = #FirstNode ∧ (tokenState = #NotTerminated ∨ id<nodeState, #FirstNode> = #NotTerminated))"
  244. apply (rule basevars_arbitrary [of LastNode MaybeTerminated "isNodeActive w" "λn. if n = FirstNode then MaybeTerminated else nodeState w n"])
  245. unfolding InitiateProbe_def enabled_def updatedFun_def
  246. by auto
  247. qed
  248.  
  249. have 3: "⊢ Enabled (∃n. PassToken n) = ((tokenPosition ≠ #FirstNode ∧ (¬ id<isNodeActive, tokenPosition> ∨ id<nodeState, tokenPosition> = #NotTerminated ∨ tokenState = #NotTerminated)))"
  250. proof (intro intI)
  251. fix w
  252. show "w ⊨ Enabled (∃n. PassToken n) = ((tokenPosition ≠ #FirstNode ∧ (¬ id<isNodeActive, tokenPosition> ∨ id<nodeState, tokenPosition> = #NotTerminated ∨ tokenState = #NotTerminated)))"
  253. apply (rule basevars_arbitrary [of "PreviousNode (tokenPosition w)" "if nodeState w (tokenPosition w) = NotTerminated then NotTerminated else tokenState w" "isNodeActive w" "λn. if n = tokenPosition w then MaybeTerminated else nodeState w n"])
  254. unfolding PassToken_def enabled_def updatedFun_def
  255. by auto
  256. qed
  257.  
  258. have 4:
  259. "⊢ Enabled Controlled = ((tokenPosition = #FirstNode ∧ (tokenState = #NotTerminated ∨ id<nodeState, #FirstNode> = #NotTerminated))
  260. ∨ (tokenPosition ≠ #FirstNode ∧ (¬ id<isNodeActive, tokenPosition> ∨ id<nodeState, tokenPosition> = #NotTerminated ∨ tokenState = #NotTerminated)))"
  261. unfolding inteq_reflection [OF 1]
  262. inteq_reflection [OF 2]
  263. inteq_reflection [OF 3]
  264. by auto
  265.  
  266. show ?thesis
  267. unfolding inteq_reflection [OF 4] by auto
  268. qed
  269.  
  270. lemmas enabled_controlled = inteq_reflection [OF enabled_controlled_lifted]
  271.  
  272. section Safety
  273.  
  274. text ‹The safety property of the algorithm says that termination is detected only if all nodes
  275. are inactive. The proof works by showing that the safety invariant is actually an invariant,
  276. and that this invariant implies the desired safety property.›
  277.  
  278. definition AllNodesInactive :: stpred where
  279. "AllNodesInactive ≡ PRED (∀ n. ¬ id<isNodeActive,#n>)"
  280.  
  281. definition SafetyInvariant where
  282. "SafetyInvariant ≡ PRED
  283. (∀ n. (tokenPosition < #n) ⟶ ¬ id<isNodeActive,#n>)
  284. ∨ (∃ n. #n ≤ tokenPosition ∧ id<nodeState,#n> = #NotTerminated)
  285. ∨ tokenState = #NotTerminated"
  286.  
  287. lemma safety:
  288. shows "⊢ Spec ⟶ □(TerminationDetected ⟶ AllNodesInactive)"
  289. proof -
  290. have "⊢ Spec ⟶ □SafetyInvariant"
  291. proof invariant
  292. fix sigma
  293. assume s: "Spec sigma"
  294. thus "sigma ⊨ Init SafetyInvariant"
  295. by (auto simp add: Spec_def SafetyInvariant_def StartState_def Init_def)
  296.  
  297. show "sigma ⊨ stable SafetyInvariant"
  298. proof (intro Stable)
  299. from s show "sigma ⊨ □[Next]_(isNodeActive, nodeState, tokenPosition, tokenState)"
  300. by (simp add: Spec_def)
  301.  
  302. show "⊢ $SafetyInvariant ∧ [Next]_(isNodeActive, nodeState, tokenPosition, tokenState) ⟶ SafetyInvariant$"
  303. proof clarsimp
  304. fix s t
  305. assume s: "SafetyInvariant s"
  306. and st: "(s, t) ⊨ [Next]_(isNodeActive, nodeState, tokenPosition, tokenState)"
  307.  
  308. from st have
  309. "((s, t) ⊨ InitiateProbe)
  310. ∨ (∃n. (s, t) ⊨ PassToken n)
  311. ∨ (∃n. (s, t) ⊨ SendMsg n)
  312. ∨ (∃n. (s, t) ⊨ Deactivate n)
  313. ∨ ((s, t) ⊨ unchanged (isNodeActive, nodeState, tokenPosition, tokenState))"
  314. by (auto simp add: square_def Next_def Controlled_def Environment_def)
  315.  
  316. thus "SafetyInvariant t"
  317. proof (elim disjE conjE exE)
  318. assume "(s, t) ⊨ unchanged (isNodeActive, nodeState, tokenPosition, tokenState)"
  319. with s show "SafetyInvariant t" by (simp add: SafetyInvariant_def)
  320. next
  321. assume "InitiateProbe (s, t)"
  322. hence step:
  323. "tokenPosition s = FirstNode" "tokenState s = NotTerminated ∨ nodeState s FirstNode = NotTerminated"
  324. "tokenPosition t = LastNode" "tokenState t = MaybeTerminated" "isNodeActive t = isNodeActive s"
  325. "⋀n. nodeState t n = (if n = FirstNode then MaybeTerminated else nodeState s n)"
  326. unfolding InitiateProbe_def updatedFun_def
  327. by auto
  328.  
  329. note step_simps[simp] = `tokenPosition s = FirstNode` `tokenPosition t = LastNode` `tokenState t = MaybeTerminated` `isNodeActive t = isNodeActive s`
  330. `⋀n. nodeState t n = (if n = FirstNode then MaybeTerminated else nodeState s n)`
  331.  
  332. show "SafetyInvariant t"
  333. unfolding SafetyInvariant_def
  334. apply (auto simp add: less_Node_def LastNode_def)
  335. by (metis Abs_Node_inverse Rep_Node Suc_pred atLeastLessThan_iff diff_Suc_less less_or_eq_imp_le neq0_conv not_less_eq)
  336.  
  337. next
  338. fix n assume "Deactivate n (s, t)"
  339. hence step:
  340. "tokenPosition t = tokenPosition s" "tokenState t = tokenState s" "nodeState t = nodeState s" "⋀n. isNodeActive t n ⟹ isNodeActive s n"
  341. unfolding Deactivate_def updatedFun_def apply auto
  342. by (metis id_apply unl_before unl_con unl_lift2)
  343.  
  344. from s show "SafetyInvariant t" by (auto simp add: less_Node_def LastNode_def SafetyInvariant_def step)
  345.  
  346. next
  347. fix sender assume step: "SendMsg sender (s, t)"
  348. from step have step_simps[simp]: "tokenPosition t = tokenPosition s" "tokenState t = tokenState s" by (auto simp add: SendMsg_def)
  349. from step have n_active: "isNodeActive s sender" by (simp add: SendMsg_def)
  350.  
  351. from step obtain receiver where receiver: "receiver ≠ sender"
  352. "⋀m. isNodeActive t m = (m = receiver ∨ isNodeActive s m)"
  353. "⋀m. nodeState t m = (if m = sender ∧ receiver > sender then NotTerminated else nodeState s m)"
  354. unfolding SendMsg_def updatedFun_def by auto
  355.  
  356. show ?thesis
  357. proof (cases "receiver < tokenPosition s")
  358. case False
  359. with s show ?thesis
  360. unfolding SafetyInvariant_def less_Node_def
  361. apply auto
  362. apply (metis le_less_trans less_Node_def n_active not_le receiver(2) receiver(3))
  363. by (metis receiver(3))
  364. next
  365. case True
  366. with s receiver show ?thesis unfolding SafetyInvariant_def less_Node_def by fastforce
  367. qed
  368.  
  369. next
  370. fix n assume step: "PassToken n (s,t)"
  371.  
  372. hence step_tokenPosition[simp]: "tokenPosition s = n" "tokenPosition t = PreviousNode n" "n ≠ FirstNode" unfolding PassToken_def by auto
  373.  
  374. from step have step_active[simp]: "isNodeActive t = isNodeActive s" unfolding PassToken_def by auto
  375.  
  376. from step have step_colour: "⋀m. nodeState t m = (if m = n then MaybeTerminated else nodeState s m)"
  377. by (simp add: PassToken_def updatedFun_def)
  378.  
  379. from step have step_tokenState: "tokenState t = (if nodeState s n = NotTerminated then NotTerminated else tokenState s)"
  380. unfolding PassToken_def by simp
  381.  
  382. show ?thesis
  383. proof (cases "nodeState s n = NotTerminated ∨ tokenState s = NotTerminated")
  384. case True with step_tokenState show ?thesis by (auto simp add: SafetyInvariant_def)
  385. next
  386. case False
  387. with TerminationState.exhaust have whites: "nodeState s n = MaybeTerminated" "tokenState s = MaybeTerminated" by auto
  388.  
  389. from whites step_colour step_tokenState have step_simps[simp]:
  390. "nodeState t = nodeState s" "tokenState t = tokenState s" by auto
  391.  
  392. from step whites have n_inactive: "¬isNodeActive s n" unfolding PassToken_def by auto
  393.  
  394. from step_tokenPosition(3)
  395. have gt1: "⋀m. m < n = (m < (PreviousNode n) ∨ m = PreviousNode n)"
  396. using Node_gt_PreviousNode not_less_iff_gr_or_eq by blast
  397.  
  398. have gt2: "⋀m. n < m = ((PreviousNode n) < m ∧ m ≠ n)"
  399. using Node_gt_PreviousNode step_tokenPosition(3) by blast
  400.  
  401. from s n_inactive show ?thesis
  402. unfolding SafetyInvariant_def
  403. apply (clarsimp simp add: gt1 gt2)
  404. by (metis TerminationState.simps(2) gt2 leD leI whites(1))
  405. qed
  406. qed
  407. qed
  408. qed
  409. qed
  410.  
  411. moreover have "⊢ □SafetyInvariant ⟶ □(TerminationDetected ⟶ AllNodesInactive)"
  412. unfolding SafetyInvariant_def
  413. proof (intro STL4, clarsimp, intro conjI impI)
  414. fix w
  415. assume inactive_gt: "∀n. (tokenPosition w < n) ⟶ ¬ isNodeActive w n"
  416. show "TerminationDetected w ⟹ AllNodesInactive w"
  417. unfolding TerminationDetected_def AllNodesInactive_def
  418. proof clarsimp
  419. fix n assume a: "isNodeActive w n" "tokenPosition w = FirstNode" "¬ isNodeActive w FirstNode"
  420. with inactive_gt have "¬ n > FirstNode" by auto
  421. hence "n = FirstNode"
  422. unfolding less_Node_def FirstNode_def
  423. by (metis Abs_Node_inverse NodeCount_positive Rep_Node Rep_Node_inject atLeastLessThan_iff le_numeral_extra(3) nat_less_le)
  424. with a show False by simp
  425. qed
  426. next
  427. fix w
  428. assume "tokenState w = NotTerminated"
  429. thus "TerminationDetected w ⟹ AllNodesInactive w"
  430. unfolding TerminationDetected_def
  431. by auto
  432. next
  433. fix w
  434. assume "∃n. (n ≤ tokenPosition w) ∧ nodeState w n = NotTerminated"
  435. then obtain n where n: "n ≤ tokenPosition w" "nodeState w n = NotTerminated" by auto
  436. thus "TerminationDetected w ⟹ AllNodesInactive w"
  437. unfolding TerminationDetected_def AllNodesInactive_def
  438. proof clarsimp
  439. assume "tokenPosition w = FirstNode" "nodeState w FirstNode = MaybeTerminated"
  440. with n show False
  441. by (metis Abs_Node_inverse TerminationState.distinct(2) FirstNode_def NodeCount_positive Rep_Node_inverse atLeastLessThan_iff le_zero_eq less_eq_Node_def)
  442. qed
  443. qed
  444.  
  445. ultimately show ?thesis by (simp add: Valid_def)
  446. qed
  447.  
  448. section Liveness
  449.  
  450. text ‹When all nodes become inactive the algorithm runs through up to three further distinct
  451. phases before detecting termination. The first phase is simply to return the token to the first
  452. node, without any constraints on its state or the states of the nodes. The second phase
  453. passes the token around the ring once more which sets each node's state to $MaybeTerminated$,
  454. although the token itself may be ``contaminated'' by a $NotTerminated$ state. The third phase
  455. passes the token around the ring one last time to remove any such contamination.›
  456.  
  457. text ‹The following predicates correspond to each step of each of these phases.›
  458.  
  459. definition AllNodesInactiveAndTokenAt where "AllNodesInactiveAndTokenAt n ≡ PRED
  460. (AllNodesInactive ∧ tokenPosition = #n)"
  461.  
  462. definition NodeCleaningRunAt where "NodeCleaningRunAt n ≡ PRED
  463. (AllNodesInactiveAndTokenAt n
  464. ∧ id<nodeState,#FirstNode> = #MaybeTerminated
  465. ∧ (∀ m. #n < #m ⟶ id<nodeState,#m> = #MaybeTerminated))"
  466.  
  467. definition TokenCleaningRunAt where "TokenCleaningRunAt n ≡ PRED
  468. (AllNodesInactiveAndTokenAt n
  469. ∧ tokenState = #MaybeTerminated
  470. ∧ (∀ m. id<nodeState,#m> = #MaybeTerminated))"
  471.  
  472. text ‹The liveness proof now shows that each phase completes and either detects termination
  473. or leads to the next phase.›
  474.  
  475. lemma step:
  476. assumes "⊢ P ⟶ AllNodesInactive"
  477. assumes "⊢ P ⟶ ¬ TerminationDetected"
  478. assumes "⊢ $P ∧ unchanged (isNodeActive, nodeState, tokenPosition, tokenState) ⟶ P$"
  479. assumes "⊢ $P ∧ Controlled ⟶ Q$"
  480. shows "⊢ Spec ⟶ (P ↝ Q)"
  481. proof -
  482. have "⊢ (□[Next]_(isNodeActive, nodeState, tokenPosition, tokenState)
  483. ∧ WF(Controlled)_(isNodeActive, nodeState, tokenPosition, tokenState)) ⟶ (P ↝ Q)"
  484. proof (intro WF1)
  485. from assms have no_Environment: "⋀s t. s ⊨ P ⟹ (s, t) ⊨ Environment ⟹ False"
  486. by (auto simp add: Environment_def AllNodesInactive_def Valid_def SendMsg_def Deactivate_def)
  487.  
  488. with assms
  489. show "⊢ $P ∧ [Next]_(isNodeActive, nodeState, tokenPosition, tokenState) ⟶ P$ ∨ Q$"
  490. "⊢ ($P ∧ [Next]_(isNodeActive, nodeState, tokenPosition, tokenState)) ∧ <Controlled>_(isNodeActive, nodeState, tokenPosition, tokenState) ⟶ Q$"
  491. "⊢ $P ∧ [Next]_(isNodeActive, nodeState, tokenPosition, tokenState) ⟶ $Enabled (<Controlled>_(isNodeActive, nodeState, tokenPosition, tokenState))"
  492. unfolding angle_Controlled enabled_controlled Next_def square_def Valid_def AllNodesInactive_def TerminationDetected_def
  493. apply simp_all
  494. apply (meson TerminationState.exhaust, blast)
  495. by (metis (full_types) TerminationState.exhaust)
  496. qed
  497.  
  498. thus ?thesis
  499. by (auto simp add: Spec_def Fairness_def)
  500. qed
  501.  
  502. lemma liveness: "⊢ Spec ⟶ (AllNodesInactive ↝ TerminationDetected)"
  503. proof -
  504. note [simp] = TokenCleaningRunAt_def NodeCleaningRunAt_def
  505. AllNodesInactiveAndTokenAt_def AllNodesInactive_def
  506. square_def Controlled_def InitiateProbe_def PassToken_def updatedFun_def
  507. TerminationDetected_def
  508.  
  509. have "⊢ Spec ⟶ (AllNodesInactive ↝ AllNodesInactiveAndTokenAt FirstNode)"
  510. proof -
  511. have "⊢ AllNodesInactive = (∃n. AllNodesInactiveAndTokenAt n)" unfolding AllNodesInactiveAndTokenAt_def by auto
  512. hence "⊢ (AllNodesInactive ↝ AllNodesInactiveAndTokenAt FirstNode)
  513. = (∀n. (AllNodesInactiveAndTokenAt n ↝ AllNodesInactiveAndTokenAt FirstNode))"
  514. by (metis inteq_reflection leadsto_exists)
  515.  
  516. moreover {
  517. fix n
  518. have "⊢ Spec ⟶ (AllNodesInactiveAndTokenAt n ↝ AllNodesInactiveAndTokenAt FirstNode)"
  519. proof (induct n rule: Node_induct)
  520. case FirstNode show ?case by (intro imp_leadsto_reflexive)
  521. next
  522. case (PreviousNode n)
  523. hence "⊢ Spec ⟶ (AllNodesInactiveAndTokenAt n ↝ AllNodesInactiveAndTokenAt (PreviousNode n))"
  524. by (intro step, auto)
  525. with PreviousNode show ?case by (metis imp_leadsto_transitive)
  526. qed
  527. }
  528.  
  529. ultimately show ?thesis by (auto simp add: Valid_def)
  530. qed
  531.  
  532. moreover have "⊢ Spec ⟶ ((AllNodesInactiveAndTokenAt FirstNode ∧ ¬ TerminationDetected) ↝ NodeCleaningRunAt LastNode)"
  533. by (intro step, auto)
  534.  
  535. moreover have "⋀n. ⊢ Spec ⟶ (NodeCleaningRunAt n ↝ NodeCleaningRunAt FirstNode)"
  536. proof -
  537. fix n show "?thesis n"
  538. proof (induct n rule: Node_induct)
  539. case FirstNode
  540. with LatticeReflexivity show ?case by auto
  541. next
  542. case (PreviousNode n)
  543. with Node_gt_PreviousNode Node_gt_ne
  544. have "⊢ Spec ⟶ (NodeCleaningRunAt n ↝ NodeCleaningRunAt (PreviousNode n))"
  545. by (intro step, auto)
  546. with PreviousNode show ?case by (metis imp_leadsto_transitive)
  547. qed
  548. qed
  549.  
  550. moreover have "⊢ Spec ⟶ (NodeCleaningRunAt FirstNode ∧ ¬ TerminationDetected ↝ TokenCleaningRunAt LastNode)"
  551. proof -
  552. have firstNode_min: "⋀n. n = FirstNode ∨ FirstNode < n"
  553. using Abs_Node_inverse FirstNode_def NodeCount_positive le_less less_eq_Node_def by fastforce
  554.  
  555. hence "⊢ NodeCleaningRunAt FirstNode
  556. = (AllNodesInactiveAndTokenAt FirstNode ∧ (∀ m. id<nodeState,#m> = #MaybeTerminated))"
  557. by (auto, force)
  558. thus ?thesis by (intro step, auto, metis firstNode_min)
  559. qed
  560.  
  561. moreover have "⋀n. ⊢ Spec ⟶ (TokenCleaningRunAt n ↝ TerminationDetected)"
  562. proof -
  563. fix n
  564. show "?thesis n"
  565. proof (induct n rule: Node_induct)
  566. case FirstNode
  567. have "⊢ TokenCleaningRunAt FirstNode ⟶ TerminationDetected" by auto
  568. hence "⊢ TokenCleaningRunAt FirstNode ↝ TerminationDetected"
  569. using ImplLeadsto_simple by auto
  570. thus ?case by (auto simp add: ImplLeadsto_simple intI tempD)
  571. next
  572. case (PreviousNode n)
  573. hence "⊢ Spec ⟶ (TokenCleaningRunAt n ↝ TokenCleaningRunAt (PreviousNode n))"
  574. by (intro step, auto, blast)
  575. with PreviousNode show ?case by (metis imp_leadsto_transitive)
  576. qed
  577. qed
  578.  
  579. ultimately show ?thesis
  580. by (metis imp_leadsto_transitive imp_leadsto_triangle_excl)
  581. qed
  582.  
  583. end
Add Comment
Please, Sign In to add comment