Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  AsynchronousSystem.thy

  Sprache: Isabelle
 

section AsynchronousSystem

text 
 \file{AsynchronousSystem} defines a message datatype and a transition system locale to
 model asynchronous distributed computation. It establishes a diamond property for a
 special reachability relation within such transition systems.
 


theory AsynchronousSystem
imports Multiset
begin

text
 The formalization is type-parameterized over
 \begin{description}
 \item[\var{'p} process identifiers.] Corresponds to the set $P$ in Völzer.
 Finiteness is not yet demanded, but will be in \file{FLPSystem}.
 \item[\var{'s} process states.] Corresponds to $S$, countability is not
 imposed.
 \item[\var{'v} message payloads.] Corresponds to the interprocess
 communication part of $M$ from Völzer. The whole of $M$ is captured by
 \isb{messageValue}.
 \end{description}
 


subsectionMessages

text 
 A \isb{message} is either an initial input message telling a process
 which value it should introduce to the consensus negotiation, a message
 to the environment communicating the consensus outcome, or a message
 passed from one process to some other.
 


datatype ('p, 'v) message =
  InMsg 'p bool  (<_, inM _>)
| OutMsg bool    (<\<bottom>, outM _>)
| Msg 'p 'v      (<_, _>)

text 
 A message value is the content of a message, which a process may receive.
 


datatype 'v messageValue = 
  Bool bool
Value 'v

primrec unpackMessage :: "('p, 'v) message ==> 'v messageValue"
where
  "unpackMessage <p, inM b> = Bool b"
"unpackMessage <p, v> = Value v"
"unpackMessage <, outM v> = Bool False"

primrec isReceiverOf :: 
  "'p ==> ('p, 'v) message ==> bool"
where 
   "isReceiverOf p1 (<p2, inM v>) = (p1 = p2)"
 | "isReceiverOf p1 (<p2, v>) = (p1 = p2)"
 | "isReceiverOf p1 (<,outM v>) = False"

lemma UniqueReceiverOf:
fixes 
  msg  :: "('p, 'v) message" and
  p q :: 'p
assumes
  "isReceiverOf q msg"
  "p q"
shows 
  "¬ isReceiverOf p msg"
using assms by (cases msg, auto)

subsectionConfigurations

text 
 Here we formalize a configuration as detailed in section 2 of Völzer's paper.

 Note that Völzer imposes the finiteness of the message multiset by
 definition while we do not do so. In \isb{FiniteMessages}
 We prove the finiteness to follow from the assumption that only
 finitely many messages can be sent at once.
 


record ('p, 'v, 's) configuration =
  states :: "'p ==> 's"
  msgs :: "(('p, 'v) message) multiset"

text 
 C.f. Völzer: \textquote{A step is identified with a message $(p, m)$. A step $(p, m)$ is enabled
 in a configuration c if $\var{msgs}_c$ contains the message $(p, m)$.}
 


definition enabled ::
  "('p, 'v, 's) configuration ==> ('p, 'v) message ==> bool"
where 
  "enabled cfg msg (msg # msgs cfg)"

subsection The system locale

text 
 The locale describing a system is derived by slight refactoring from the
 following passage of Völzer:
 \begin{displayquote}
 A process $p$ consists of an initial state $s_p \in S$ and a step transition
 function, which assigns to each pair $(m, s)$ of a message value $m$ and
 a process state $s$ a follower state and a finite set of messages (the
 messages to be sent by $p$ in a step).
 \end{displayquote}
 


locale asynchronousSystem =
fixes 
  trans :: "'p ==> 's ==> 'v messageValue ==> 's" and
  sends :: "'p ==> 's ==> 'v messageValue ==> ('p, 'v) message multiset" and
  start :: "'p ==> 's"
begin

abbreviation Proc :: "'p set"
where "Proc (UNIV :: 'p set)"

subsection The step relation

text 
 The step relation is defined analogously to Völzer:
 \begin{displayquote}
 {[}If enabled, a step may{]} occur, resulting in a follower
 configuration $c^\prime$, where $c^\prime$ is obtained from $c$ by removing
 $(p, m)$ from $\var{msgs}_c$, changing $p$'s state and adding the set of
 messages to $\var{msgs}_c$ according to the step transition function
 associated with $p$. We denote this by $c \xrightarrow{p,m} c^\prime$.
 \end{displayquote}
 There are no steps consuming output messages.
 


primrec steps :: 
  "('p, 'v, 's) configuration
   ==> ('p, 'v) message
   ==> ('p, 'v, 's) configuration
   ==> bool"
   (_ _ _ [70,70,70])
where 
  StepInMsg: "cfg1 <p, inM v> cfg2 = (
  ( s. ((s = p) states cfg2 p = trans p (states cfg1 p) (Bool v))
       ((s p) states cfg2 s = states cfg1 s))
    enabled cfg1 <p, inM v>
    msgs cfg2 = (sends p (states cfg1 p) (Bool v)
                  # (msgs cfg1 -# <p, inM v>)))"
| StepMsg: "cfg1 <p, v> cfg2 = (
  ( s. ((s = p) states cfg2 p = trans p (states cfg1 p) (Value v))
       ((s p) states cfg2 s = states cfg1 s))
    enabled cfg1 <p, v>
    msgs cfg2 = (sends p (states cfg1 p) (Value v)
                  # (msgs cfg1 -# <p, v>)))"
| StepOutMsg: "cfg1 <,outM v> cfg2 =
    False"

text 
 The system is distributed and asynchronous in the sense that the processing
 of messages only affects the process the message is directed to while the
 rest stays unchanged.
 

lemma NoReceivingNoChange:
fixes
  cfg1 cfg2 :: "('p,'v,'s) configuration" and
  m :: "('p,'v) message" and
  p :: 'p
assumes
  Step: "cfg1 m cfg2" and
  Rec: "¬ isReceiverOf p m"
shows
  "states cfg1 p = states cfg2 p "
proof(cases m)
  case (OutMsg b')
  thus ?thesis using Step by auto
next
  case (InMsg q b')
  assume CaseM:  "m = <q, inM b'>"
  with assms have "p q" by simp
  with Step CaseM show ?thesis by simp
next
  case (Msg q v')
  assume CaseM:  "m = <q, v'>"
  with assms have "p q" by simp
  with Step CaseM show ?thesis by simp
qed

lemma ExistsMsg:
fixes
  cfg1 cfg2 :: "('p,'v,'s) configuration" and
  m :: "('p,'v) message"
assumes
  Step: "cfg1 m cfg2"
shows
  "m # (msgs cfg1)"
using assms enabled_def by (cases m, auto)

lemma NoMessageLossStep:
fixes
  cfg1 :: "('p,'v,'s) configuration" and
  cfg2 :: "('p,'v,'s) configuration" and
  p :: 'p and
  m :: "('p,'v) message" and
  m' :: "('p,'v) message"
assumes
  Step: "cfg1 m cfg2" and
  Rec1: "isReceiverOf p m" and
  Rec2: "¬isReceiverOf p m'"
shows 
  "msgs cfg1 m' msgs cfg2 m'"
using assms by (induct m, simp_all, auto)

lemma OutOnlyGrowing:
fixes 
  cfg1 cfg2 :: "('p,'v,'s) configuration" and
  b::bool and
  m::"('p, 'v) message" and
  p::'p
assumes
  "cfg1 m cfg2"
  "isReceiverOf p m"
shows 
  "msgs cfg2 <, outM b>
  = (msgs cfg1 <, outM b>) +
    sends p (states cfg1 p) (unpackMessage m) <, outM b>" 
proof(-)
  have "m = <, outM b> ==> False" using assms proof(auto) qed
  hence MNotOut: "m <, outM b>" by auto
  have MsgFunction: "msgs cfg2
                    = ((sends p (states cfg1 p) (unpackMessage m))
                      # ((msgs cfg1) -# m))"
  proof(cases m) 
    case (InMsg pa bool)
    then have PaIsP: "pa = p" "(unpackMessage m) = Bool bool" 
      using isReceiverOf_def assms(2by (auto simp add: UniqueReceiverOf)
    hence "cfg1 <p, inM bool> cfg2" using assms(1) InMsg by simp
    hence "msgs cfg2 = (sends p (states cfg1 p) (Bool bool)
                       # (msgs cfg1 -# <p, inM bool>))" 
      by simp
    hence "msgs cfg2 = (sends p (states cfg1 p) (Bool bool)
                       # (msgs cfg1 -# m))" 
      using PaIsP(1) InMsg by simp
    thus ?thesis using StepInMsg assms PaIsP by simp
  next case (OutMsg b)
    hence False using assms by auto
    thus ?thesis by simp
  next case (Msg pa va)
    hence PaIsP: "pa = p" "(unpackMessage m) = Value va" 
      using isReceiverOf_def assms(2by (auto simp add: UniqueReceiverOf)
    hence "cfg1 <p, va> cfg2" using assms(1) Msg by simp
    hence "msgs cfg2 = (sends p (states cfg1 p) (Value va)
                       # (msgs cfg1 -# <p, va>))" by simp
    hence "msgs cfg2 = (sends p (states cfg1 p) (Value va)
                       # (msgs cfg1 -# m))" 
      using PaIsP(1) Msg by simp
    thus ?thesis using StepInMsg assms PaIsP by simp
  qed
  have "((sends p (states cfg1 p) (unpackMessage m))
         # ((msgs cfg1) -# m)) <, outM b>
       = ((sends p (states cfg1 p) (unpackMessage m))
         # (msgs cfg1)) <, outM b>"
    using MNotOut by auto
  thus "msgs cfg2 <, outM b>
       = (msgs cfg1 <, outM b>) +
         sends p (states cfg1 p) (unpackMessage m) <, outM b>" 
    using MsgFunction by simp
qed

lemma OtherMessagesOnlyGrowing:
fixes
  cfg1 :: "('p,'v,'s) configuration" and
  cfg2 :: "('p,'v,'s) configuration" and
  p :: 'p and
  m :: "('p,'v) message" and
  m' :: "('p,'v) message"
assumes
  Step: "cfg1 m cfg2" and
  "m m'"
shows
  "msgs cfg1 m' msgs cfg2 m'"
using assms by (cases m, auto)

text 
 Völzer: \textquote{Note that steps are enabled persistently, i.e., an
 enabled step remains enabled as long as it does not occur.}
 

lemma OnlyOccurenceDisables:
fixes
  cfg1 :: "('p,'v,'s) configuration" and
  cfg2 :: "('p,'v,'s) configuration" and
  p :: 'p and
  m :: "('p,'v) message" and
  m' :: "('p,'v) message"
assumes
  Step: "cfg1 m cfg2" and
  En: "enabled cfg1 m'" and
  NotEn: "¬ (enabled cfg2 m')"
shows
  "m = m'"
using assms proof (cases m) print_cases
  case (InMsg p bool)
  with Step have "msgs cfg2 = (sends p (states cfg1 p) (Bool bool)
                              # (msgs cfg1 -# <p, inM bool>))" by auto
  thus "m = m'" using InMsg En NotEn 
    by (auto simp add: enabled_def, metis less_nat_zero_code)
next
  case (OutMsg bool)
  with Step show "m = m'" by auto
next
  case (Msg p v)
  with Step have "msgs cfg2 = (sends p (states cfg1 p) (Value v)
                              # (msgs cfg1 -# <p, v>))" by auto
  thus "m = m'" using Msg En NotEn 
    by (auto simp add: enabled_def, metis less_nat_zero_code)
qed

subsection Reachability

inductive reachable :: 
  " ('p, 'v, 's) configuration
  ==> ('p, 'v, 's) configuration
  ==> bool"
where 
  init: "reachable cfg1 cfg1"
| step: "[ reachable cfg1 cfg2; (cfg2 msg cfg3) ]
          ==> reachable cfg1 cfg3"

lemma ReachableStepFirst: 
assumes
  "reachable cfg cfg'"
shows 
  "cfg = cfg' ( cfg1 msg p . (cfg msg cfg1) enabled cfg msg
                     isReceiverOf p msg
                     reachable cfg1 cfg')" 
using assms 
by (induct rule: reachable.induct, auto, 
    metis StepOutMsg ExistsMsg init enabled_def isReceiverOf.simps(1
    isReceiverOf.simps(2) message.exhaust, metis asynchronousSystem.step)

lemma ReachableTrans: 
fixes 
  cfg1 cfg2 cfg3 :: "('p, 'v, 's ) configuration" and 
  Q :: " 'p set"
assumes 
  "reachable cfg1 cfg2" and 
  "reachable cfg2 cfg3"
shows "reachable cfg1 cfg3"
proof - 
  have "reachable cfg2 cfg3 ==> reachable cfg1 cfg2 ==> reachable cfg1 cfg3" 
  proof (induct rule: reachable.induct, auto)
    fix cfg1' cfg2' msg cfg3'
    assume 
      "reachable cfg1 cfg2'"
      "cfg2' msg cfg3'"
    thus "reachable cfg1 cfg3'" using reachable.simps by metis
  qed
  thus ?thesis using assms by simp
qed

definition stepReachable ::
    "('p, 'v, 's) configuration
  ==> ('p ,'v) message
  ==> ('p, 'v, 's) configuration
  ==> bool" 
where
  "stepReachable c1 msg c2
     c' c''. reachable c1 c' (c' msg c'') reachable c'' c2 "

lemma StepReachable:
fixes
  cfg cfg' :: "('p,'v,'s) configuration" and
  msg :: "('p, 'v) message"
assumes
  "reachable cfg cfg'" and
  "enabled cfg msg" and
  "¬ (enabled cfg' msg)"
shows "stepReachable cfg msg cfg'" 
using assms
proof(induct rule: reachable.induct, simp)
  fix cfg1 cfg2 msga cfg3
  assume Step: "cfg2 msga cfg3" and
    ReachCfg1Cfg2: "reachable cfg1 cfg2" and
    IV: "(enabled cfg1 msg ==> ¬ enabled cfg2 msg
        ==> stepReachable cfg1 msg cfg2)" and
    AssumpInduct: "enabled cfg1 msg" "¬ enabled cfg3 msg"
  have ReachCfg2Cfg3: "reachable cfg2 cfg3" using Step 
    by (metis reachable.init reachable.step)
  show "stepReachable cfg1 msg cfg3" 
  proof (cases "enabled cfg2 msg")
    assume AssumpEnabled: "enabled cfg2 msg"
    hence "msga = msg" using OnlyOccurenceDisables Step AssumpInduct(2by blast
    thus "stepReachable cfg1 msg cfg3" using ReachCfg1Cfg2 Step 
      unfolding stepReachable_def by (metis init)
  next
    assume AssumpNotEnabled: "¬ enabled cfg2 msg"
    hence "stepReachable cfg1 msg cfg2" using IV AssumpInduct(1by simp
    thus "stepReachable cfg1 msg cfg3"
      using ReachCfg2Cfg3 ReachableTrans asynchronousSystem.stepReachable_def
      by blast
  qed
qed

subsection Reachability with special process activity

text 
 We say that \isb{qReachable cfg1 Q cfg2} iff cfg2 is reachable from cfg1
 only by activity of processes from Q.
 

inductive qReachable ::
  "('p,'v,'s) configuration
  ==> 'p set
  ==> ('p,'v,'s) configuration
  ==> bool"
where  
  InitQ: "qReachable cfg1 Q cfg1"
| StepQ: "[ qReachable cfg1 Q cfg2; (cfg2 msg cfg3) ;
             p Q . isReceiverOf p msg ]
          ==> qReachable cfg1 Q cfg3"

text 
 We say that \isb{withoutQReachable cfg1 Q cfg2} iff cfg2 is reachable from cfg1
 with no activity of processes from Q.
 

abbreviation withoutQReachable ::
   "('p,'v,'s) configuration
  ==> 'p set
  ==> ('p,'v,'s) configuration
  ==> bool"
where
  "withoutQReachable cfg1 Q cfg2
    qReachable cfg1 ((UNIV :: 'p set ) - Q) cfg2"

text
 Obviously q-reachability (and thus also without-q-reachability) implies
 reachability.
 

lemma QReachImplReach:
fixes
  cfg1 cfg2::  "('p, 'v, 's ) configuration" and
  Q :: " 'p set"
assumes
  "qReachable cfg1 Q cfg2"
shows 
  "reachable cfg1 cfg2"
using assms 
proof (induct rule: qReachable.induct)
  case InitQ thus ?case using reachable.simps by blast
next
  case StepQ thus ?case using reachable.step by simp
qed

lemma QReachableTrans: 
fixes cfg1 cfg2 cfg3 :: "('p, 'v, 's ) configuration" and
  Q :: " 'p set"
assumes "qReachable cfg2 Q cfg3" and
  "qReachable cfg1 Q cfg2"
shows "qReachable cfg1 Q cfg3"
using assms
proof (induct rule: qReachable.induct, simp)
  case (StepQ)
  thus ?case using qReachable.simps by metis
qed

lemma NotInQFrozenQReachability: 
fixes
  cfg1 cfg2 :: "('p,'v,'s) configuration" and
  p :: 'p and
  Q :: "'p set"
assumes
  "qReachable cfg1 Q cfg2" and
  "p Q"
shows
  "states cfg1 p = states cfg2 p"
using assms 
proof(induct rule: qReachable.induct, auto)
  fix cfg1' Q' cfg2' msg cfg3 p'
  assume "qReachable cfg1' Q' cfg2'"
  assume Step: "cfg2' msg cfg3"
  assume Rec: "isReceiverOf p' msg"
  assume "p' Q'"  "p Q'"
  hence notEq: "p p'" by blast
  with Rec have "¬ (isReceiverOf p msg)" by (cases msg, simp_all)
  thus "states cfg2' p = states cfg3 p"
    using Step NoReceivingNoChange by simp
qed

corollary WithoutQReachablFrozenQ:
fixes
  cfg1 cfg2 :: "('p,'v,'s) configuration" and
  p :: 'p and
  Q :: "'p set"
assumes
  Steps: "withoutQReachable cfg1 Q cfg2" and
  P: "p Q"
shows
  "states cfg1 p = states cfg2 p"
using assms NotInQFrozenQReachability by simp

lemma NoActivityNoMessageLoss :
fixes
  cfg1 cfg2 :: "('p,'v,'s) configuration" and
  p :: 'p and
  Q :: "'p set" and
  m' :: "('p, 'v) message"
assumes
  "qReachable cfg1 Q cfg2" and
  "p Q" and
  "isReceiverOf p m'"
shows
  "(msgs cfg1 m') (msgs cfg2 m')"
using assms
proof (induct rule: qReachable.induct, simp)
  case (StepQ cfg1' Q' cfg2' msg cfg3)
  then obtain p' where
    P': "p' Q'" "isReceiverOf p' msg" "p p'" by blast
  with assms(3have "¬(isReceiverOf p' m')" 
    by (cases m', simp_all)
  with NoMessageLossStep StepQ(3) P'
    have "msgs cfg2' m' msgs cfg3 m'" 
    by simp
  with StepQ
    show "msgs cfg1' m' msgs cfg3 m'" by simp
qed

lemma NoMessageLoss:
fixes
  cfg1 cfg2 :: "('p,'v,'s) configuration" and
  p :: 'p and
  Q :: "'p set" and
  m' :: "('p, 'v) message"
assumes
  "withoutQReachable cfg1 Q cfg2" and
  "p Q" and
  "isReceiverOf p m'"
shows
  "(msgs cfg1 m') (msgs cfg2 m')" 
using assms NoActivityNoMessageLoss by simp

lemma NoOutMessageLoss:
fixes
  cfg1 cfg2 :: "('p,'v,'s) configuration" and
  v :: bool
assumes
  "reachable cfg1 cfg2"
shows
  "(msgs cfg1 <, outM v>) (msgs cfg2 <, outM v>)"
using assms 
proof(induct rule: reachable.induct, auto)
  fix cfg1 cfg' msg cfg2
  assume AssInduct:
    "reachable cfg1 cfg'"
    "msgs cfg1 <, outM v> msgs cfg' <, outM v>" 
    "cfg' msg cfg2"
  from AssInduct(3have "msgs cfg' <, outM v> msgs cfg2 <, outM v>"  
    by (cases msg, auto)
  with AssInduct(2show " msgs cfg1 <, outM v> msgs cfg2 <, outM v>"
    using le_trans by blast
qed 

lemma StillEnabled:
fixes 
  cfg1 cfg2:: "('p,'v,'s) configuration" and
  p :: 'p and
  msg :: "('p,'v) message" and
  Q :: "'p set"
assumes 
  "withoutQReachable cfg1 Q cfg2" and
  "p Q" and
  "isReceiverOf p msg" and
  "enabled cfg1 msg"
shows
  "enabled cfg2 msg"
using assms enabled_def NoMessageLoss 
  by (metis le_0_eq neq0_conv)

subsectionInitial reachability

definition initial :: 
  "('p, 'v, 's) configuration ==> bool"
where
  "initial cfg
        ( p::'p . ( v::bool . ((msgs cfg (<p, inM v>)) = 1)))
       ( p m1 m2 . ((m1 # (msgs cfg)) (m2 # (msgs cfg))
          isReceiverOf p m1 isReceiverOf p m2) (m1 = m2))
       ( v::bool . (msgs cfg) (<, outM v>) = 0)
       ( p v. (msgs cfg) (<p, v>) = 0)
       states cfg = start"

definition initReachable ::
  "('p, 'v, 's) configuration ==> bool"
where
  "initReachable cfg cfg0 . initial cfg0 reachable cfg0 cfg"

lemma InitialIsInitReachable :
assumes "initial c"
shows "initReachable c"
  using assms reachable.init
  unfolding initReachable_def by blast

subsection Diamond property of reachability

lemma DiamondOne:
fixes
  cfg cfg1 cfg2 :: "('p,'v,'s) configuration" and
  p q :: 'p and
  m m' :: "('p,'v) message"
assumes
  StepP: "cfg m cfg1" and
  PNotQ: "p q" and
  Rec: "isReceiverOf p m" "¬ (isReceiverOf p m')" and
  Rec': "isReceiverOf q m'" "¬ (isReceiverOf q m)" and
  StepWithoutP: "cfg m' cfg2"
shows
  " cfg' :: ('p,'v,'s) configuration . (cfg1 m' cfg')
         (cfg2 m cfg')"
proof (cases m)
  case (InMsg p b)
  from StepWithoutP ExistsMsg have " m' # (msgs cfg) " by simp          
  hence "m' # (msgs cfg1)" 
    using StepP Rec NoMessageLossStep le_neq_implies_less le_antisym 
    by (metis  gr_implies_not0 neq0_conv)
  hence EnM': "enabled cfg1 m'" using enabled_def by auto
  from StepP ExistsMsg have "m # (msgs cfg) " by simp
  hence "m # (msgs cfg2)"
    using StepWithoutP Rec' NoMessageLossStep
    by (metis le_0_eq neq0_conv)
  hence EnM: "enabled cfg2 m" using enabled_def by auto
  assume CaseM:  "m = <p, inM b>"
  
  thus ?thesis 
  proof (cases m') 
    case (OutMsg b')
    thus ?thesis using StepWithoutP by simp
  next
    case (InMsg q b')
    define cfg' where "cfg' = (states = λs. (
      if s = q then
        trans q (states cfg q) (Bool b')
      else if s = p then
        trans p (states cfg p) (Bool b)
      else
        states cfg s),
      msgs = ((sends q (states cfg q) (Bool b'))
        # (((sends p (states cfg p) (Bool b))
            # ((msgs cfg)-# m)) -# m'))) "
    have StepP': "(cfg1 m' cfg')"
      using StepP  EnM' Rec
      unfolding cfg'_def InMsg CaseM by auto
    moreover from EnM have "(cfg2 m cfg')"
      using InMsg cfg'_def StepP StepP' StepWithoutP NoReceivingNoChange  
            Rec' CaseM EnM'
    proof (simp, clarify)
      assume msgCfg:
        "msgs cfg1 = (sends p (states cfg p) (Bool b)
                     # (msgs cfg -# <p, inM b>))"
        "msgs cfg2 = (sends q (states cfg q) (Bool b')
                     # (msgs cfg -# <q, inM b'>))"
      have "enabled cfg m" "enabled cfg m'" 
        using StepP StepWithoutP CaseM InMsg 
        by auto
      with msgCfg show 
        "(sends q (states cfg q) (Bool b') # (msgs cfg1 -# <q, inM b'>)) =
         (sends p (states cfg p) (Bool b) # (msgs cfg2 -# <p, inM b>))"
        using CaseM InMsg StepP StepWithoutP Rec' AXc[of "m'" "m" "msgs cfg"
          "sends q (states cfg q) (Bool b')" 
          "sends p (states cfg p) (Bool b)"]         
        unfolding enabled_def
        by metis
    qed
    ultimately show ?thesis by blast
  next
    case (Msg q v')
    define cfg' where "cfg' = (states = λs. (
      if s = q then
        trans q (states cfg q) (Value v')
      else if s = p then
        trans p (states cfg p) (Bool b)
      else
        states cfg s),
      msgs = ((sends q (states cfg q) (Value v'))
        # (((sends p (states cfg p) (Bool b))
            # ((msgs cfg)-# m))
            -# m')))"
    have StepP': "(cfg1 m' cfg')"
      using StepP EnM' Rec
      unfolding Msg CaseM cfg'_def by auto

    moreover from EnM have "(cfg2 m cfg')"
      using Msg cfg'_def StepP StepP' StepWithoutP NoReceivingNoChange Rec' CaseM EnM'
    proof (simp,clarify) 
      assume msgCfg1:
        "msgs cfg1 = (sends p (states cfg p) (Bool b)
                      # (msgs cfg -# <p, inM b>))"
        "msgs cfg2 = (sends q (states cfg q) (Value v')
                      # (msgs cfg -# <q, v'>))" 
      have "enabled cfg m" "enabled cfg m'" 
        using StepP StepWithoutP CaseM Msg 
        by auto
      with msgCfg1 show 
        "(sends q (states cfg q) (Value v') # (msgs cfg1 -# <q, v'>)) =
         (sends p (states cfg p) (Bool b) # (msgs cfg2 -# <p, inM b>))"
        using CaseM Msg StepP StepWithoutP Rec' AXc[of "m'" "m" "msgs cfg"
          "sends q (states cfg q) (Value v')" 
          "sends p (states cfg p) (Bool b)"]
        unfolding enabled_def by metis
    qed
    ultimately show ?thesis by blast
  qed
next
  case (OutMsg b)
  thus ?thesis using StepP by simp
next
  case (Msg p v)
  from StepWithoutP ExistsMsg have " m' # (msgs cfg) " by simp
  hence "m' # (msgs cfg1)" 
    using StepP Rec NoMessageLossStep le_neq_implies_less le_antisym 
    by (metis  gr_implies_not0 neq0_conv)
  hence EnM': "enabled cfg1 m'" using enabled_def by auto
  from StepP ExistsMsg have "m # (msgs cfg) " by simp
  hence "m # (msgs cfg2)"
    using StepWithoutP Rec' NoMessageLossStep
    by (metis le_0_eq neq0_conv)
  hence EnM: "enabled cfg2 m" using enabled_def by auto
  assume CaseM:  "m = <p, v>" 
  thus ?thesis 
  proof (cases m')
    case (OutMsg b')
    thus ?thesis using StepWithoutP by simp
  next
    case (InMsg q b')
    define cfg' where "cfg' = (states = λs. (
      if s = q then
        trans q (states cfg q) (Bool b')
      else if s = p then
        trans p (states cfg p) (Value v)
      else
        states cfg s),
      msgs = ((sends q (states cfg q) (Bool b'))
        # (((sends p (states cfg p) (Value v))
        # ((msgs cfg)-# m))
        -# m'))) "
    hence StepP': "(cfg1 m' cfg')"
      using StepP InMsg EnM' Rec CaseM
      by auto
    moreover from EnM have "(cfg2 m cfg')"
      using InMsg cfg'_def StepP StepP' StepWithoutP NoReceivingNoChange Rec' 
            CaseM EnM'
    proof (simp, clarify)
      assume msgCfg:
        "msgs cfg1 = (sends p (states cfg p) (Value v)
          # (msgs cfg -# <p, v>))"
        "msgs cfg2 = (sends q (states cfg q) (Bool b')
          # (msgs cfg -# <q, inM b'>))"
      have "enabled cfg m" "enabled cfg m'"
        using StepP StepWithoutP CaseM InMsg by auto
      with msgCfg show " (sends q (states cfg q) (Bool b')
                         # (msgs cfg1 -# <q, inM b'>))
                       = (sends p (states cfg p) (Value v)
                         # (msgs cfg2 -# <p, v>))"
        using CaseM StepP StepWithoutP Rec' InMsg AXc[of "m'" "m" "msgs cfg"
          "sends q (states cfg q) (Bool b')"
          "sends p (states cfg p) (Value v)"]
          unfolding enabled_def by metis
    qed
    ultimately show ?thesis by blast
  next
    case (Msg q v')
    define cfg' where "cfg' = (states = λs. (
      if s = q then
        trans q (states cfg q) (Value v')
      else if s = p then
        trans p (states cfg p) (Value v)
      else
        states cfg s),
      msgs = ((sends q (states cfg q) (Value v'))
        # (((sends p (states cfg p) (Value v))
        # ((msgs cfg)-# m))
        -# m'))) "
    hence StepP': "(cfg1 m' cfg')"
      using StepP Msg EnM' Rec CaseM by auto
    moreover from EnM have "(cfg2 m cfg')"
      using Msg cfg'_def StepP StepP' StepWithoutP NoReceivingNoChange Rec' CaseM EnM'
    proof (simp, clarify)
      assume msgCfg:
        "msgs cfg1 = (sends p (states cfg p) (Value v)
          # (msgs cfg -# <p, v>))"
        "msgs cfg2 = (sends q (states cfg q) (Value v')
          # (msgs cfg -# <q, v'>))"
      have "enabled cfg m" "enabled cfg m'"
        using StepP StepWithoutP CaseM Msg by auto

      with msgCfg show " (sends q (states cfg q) (Value v')
                         # (msgs cfg1 -# <q, v'>))
                       = (sends p (states cfg p) (Value v)
                         # (msgs cfg2 -# <p, v>))"
        using CaseM StepP StepWithoutP Rec' Msg 
          AXc[of "m'" "m" "msgs cfg" "sends q (states cfg q) (Value v')"
          "sends p (states cfg p) (Value v)"]
        unfolding enabled_def by metis
    qed
    ultimately show ?thesis by blast          
  qed
qed

lemma DiamondTwo:
fixes
  cfg cfg1 cfg2 :: "('p,'v,'s) configuration" and
  Q :: "'p set" and
  msg :: "('p, 'v) message"
assumes
  QReach: "qReachable cfg Q cfg1" and
  Step: "cfg msg cfg2"
        "pProc - Q. isReceiverOf p msg"
shows
  " (cfg' :: ('p,'v,'s) configuration) . (cfg1 msg cfg')
   qReachable cfg2 Q cfg'"
using assms 
proof(induct rule: qReachable.induct)
  fix cfg Q
  have "qReachable cfg2 Q cfg2" using qReachable.simps(1by blast
  moreover assume "cfg msg cfg2" "pUNIV - Q. isReceiverOf p msg"
  ultimately have "(cfg msg cfg2) qReachable cfg2 Q cfg2" by blast
  thus "cfg'.(cfg msg cfg') qReachable cfg2 Q cfg'" by blast
next
  fix cfg Q cfg1' msga cfg1
  assume   "(cfg msg cfg2)"
    "(pUNIV - Q. isReceiverOf p msg)"
    "((cfg msg cfg2) ==>
     (pUNIV - Q. isReceiverOf p msg) ==>
     (cfg'. (cfg1' msg cfg') qReachable cfg2 Q cfg'))"
  hence "(cfg'. (cfg1' msg cfg') (pUNIV - Q. isReceiverOf p msg)
         qReachable cfg2 Q cfg')" by blast
  then obtain cfg' where Cfg': "(cfg1' msg cfg')" 
    "(pUNIV - Q. isReceiverOf p msg)" "qReachable cfg2 Q cfg'" by blast
  then obtain p where P: "pUNIV - Q" "isReceiverOf p msg" by blast
  assume Step2: "(cfg1' msga cfg1)"
    "(pQ. isReceiverOf p msga)"
    "(qReachable cfg Q cfg1')"
  then obtain p' where P': "p'Q" "isReceiverOf p' msga" by blast
  from P'(1) P(1have notEq: "p p'" by blast
  with P(2) P'(2have "¬ isReceiverOf p' msg" "¬ isReceiverOf p msga"
    using UniqueReceiverOf[of p' msga p] UniqueReceiverOf[of p msg p']
    by auto
  with notEq P'(2) P(2) Cfg'(1) Step2(1have 
    "cfg''. (cfg' msga cfg'') (cfg1 msg cfg'')"
    using DiamondOne by simp
  then obtain cfg'' where Cfg'': "cfg' msga cfg''" "cfg1 msg cfg''" 
    by blast
  from Cfg''(1) Step2(2) Cfg'(3have "qReachable cfg2 Q cfg''" 
    using qReachable.simps[of cfg2 Q cfg''] by auto
  with Cfg'(2) Cfg''(2have 
    "(cfg1 msg cfg'') qReachable cfg2 Q cfg''"  by simp
  thus "cfg'. (cfg1 msg cfg') qReachable cfg2 Q cfg'" by blast 
qed

text Proposition 1 of Völzer.
lemma Diamond:
fixes
  cfg cfg1 cfg2 :: "('p,'v,'s) configuration" and
  Q :: "'p set"
assumes
  QReach: "qReachable cfg Q cfg1" and
  WithoutQReach: "withoutQReachable cfg Q cfg2"
shows 
  " cfg'. withoutQReachable cfg1 Q cfg'
      qReachable cfg2 Q cfg'"
proof -
  define notQ where "notQ UNIV - Q"
  with WithoutQReach have "qReachable cfg notQ cfg2" by simp
  thus ?thesis using QReach notQ_def
  proof (induct rule: qReachable.induct)
    fix cfg2
    assume "qReachable cfg2 Q cfg1"
    moreover have "qReachable cfg1 (UNIV - Q) cfg1"
      using qReachable.simps by blast
    ultimately show 
      "cfg'. qReachable cfg1 (UNIV - Q) cfg'
         qReachable cfg2 Q cfg'"  
      by blast
  next
    fix cfg cfg2' cfg2 msg
    assume Ass1: " qReachable cfg Q cfg1" "qReachable cfg (UNIV - Q) cfg2' " 
    assume Ass2:  "cfg2' msg cfg2" "pUNIV - Q. isReceiverOf p msg"
    assume "qReachable cfg Q cfg1 ==> cfg'. qReachable cfg1 (UNIV - Q) cfg'
       qReachable cfg2' Q cfg'"
    with Ass1(1have "cfg'. qReachable cfg1 (UNIV - Q) cfg'
       qReachable cfg2' Q cfg'" by blast
    then obtain cfg' where 
      Cfg'1"qReachable cfg2' Q cfg'" and 
      Cfg':  "qReachable cfg1 (UNIV - Q) cfg'" by blast
    from Cfg'1 Ass2 have 
      "cfg''.(cfg' msg cfg'') qReachable cfg2 Q cfg''" 
      using DiamondTwo by simp
    then obtain cfg'' where
      Cfg'': "cfg' msg cfg''" "qReachable cfg2 Q cfg''" by blast
    from Cfg' Cfg''(1) Ass2(2have "qReachable cfg1 (UNIV - Q) cfg''"  
      using qReachable.simps[of cfg1 "UNIV-Q" cfg''] by auto
    with Cfg'' show 
      "cfg'. qReachable cfg1 (UNIV - Q) cfg'
         qReachable cfg2 Q cfg'" by blast
  qed
qed

subsection Invariant finite message count

lemma FiniteMessages:
fixes 
  cfg  :: "('p, 'v, 's) configuration"
assumes
  FiniteProcs: "finite Proc" and
  FiniteSends: " p s m. finite {v. v # (sends p s m)}" and
  InitReachable: "initReachable cfg"
shows "finite {msg . msg # msgs cfg}"
proof(-)
  have " init . initial init reachable init cfg" using assms 
    unfolding initReachable_def by simp
  then obtain init where Init: "initial init" "reachable init cfg" 
    by blast
  have InitMsgs:"{msg . msg # msgs init}
    = { msg . (msg # msgs init) ( p v. <p, v> = msg)}
       { msg . (msg # msgs init) ( v. <, outM v> = msg)}
       { msg . (msg # msgs init) ( p v. <p, inM v> = msg)}" 
       by (auto,metis message.exhaust)
  have A:"{ msg . (msg # msgs init) ( p v. <p, v> = msg)} = {}" 
  using initial_def[of init] Init(1)by (auto, metis less_not_refl3)
  have B:"{ msg . (msg # msgs init) ( v. <, outM v> = msg)} = {}" 
  using initial_def[of init] Init(1by (auto, metis less_not_refl3)
  have " p . finite {<p, inM True>, <p, inM False>}" by auto
  moreover have SubsetMsg:
    " p. { msg . (msg # msgs init)
       ( v::bool . <p, inM v> = msg)}
       {<p, inM True>, <p, inM False>}" by auto
  ultimately have AllFinite:
    " p. finite { msg . (msg # msgs init)
       ( v::bool . <p, inM v> = msg)}"
    using finite_subset by (clarify, auto)
  have " { msg . (msg # msgs init)
     ( pProc . v::bool. <p, inM v> = msg)}
      = ( p Proc . { msg . (msg # msgs init)
     ( v::bool . <p, inM v> = msg)})" by auto
  hence "finite { msg . (msg # msgs init)
     ( pProc . v::bool. <p, inM v> = msg)}" 
    using AllFinite FiniteProcs by auto
  hence InitFinite:"finite {msg . msg # msgs init}" 
    by (auto simp add: A B InitMsgs) 
  show ?thesis using Init(2) InitFinite
  proof(induct rule: reachable.induct, simp_all)
    fix cfg1 cfg2 msg cfg3
    assume assmsInduct:"reachable cfg1 cfg2" 
      "finite {msg. msg # msgs cfg2}" "cfg2 msg cfg3" 
      "finite {msg. msg # msgs cfg1}" "reachable init cfg" 
      "finite {msg. msg # msgs init}"
    from assmsInduct(3obtain p where "isReceiverOf p msg " 
      by (metis StepOutMsg isReceiverOf.simps(1) isReceiverOf.simps(2
       message.exhaust)
    hence "msgs cfg3 = ((msgs cfg2 -# msg) # (sends p (states cfg2 p)
      (unpackMessage msg) ))" 
      using assmsInduct(3by (cases msg, auto simp add: add.commute)
    hence MsgSet: "{msg. msg # msgs cfg3 }
      = {m. m # ((msgs cfg2 -# msg) # (sends p (states cfg2 p)
        (unpackMessage msg) )) } " by simp
    have "{v. v # (msgs cfg2 -# msg)} {msg. msg # msgs cfg2}"
      by auto
    from finite_subset[OF this]
      have "finite {v. (v # sends p (states cfg2 p) (unpackMessage msg))
         (v # (msgs cfg2 -# msg))}"
      using FiniteSends assmsInduct(2by auto
    thus "finite {msg. msg # msgs cfg3}"
       unfolding MsgSet by auto
  qed
qed

end

end

Messung V0.5 in Prozent
C=93 H=95 G=93

¤ Dauer der Verarbeitung: 0.20 Sekunden  (vorverarbeitet am  2026-06-10) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge