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


Quelle  Message.thy

  Sprache: Isabelle
 

(*  Title:      HOL/Metis_Examples/Message.thy
  Author: Lawrence C. Paulson, Cambridge University Computer Laboratory
  Author: Jasmin Blanchette, TU Muenchen
 
 Metis example featuring message authentication.
*)

section Metis Example Featuring Message Authentication

theory Message
imports Main
begin

declare [[metis_new_skolem]]

lemma strange_Un_eq [simp]: "A (B A) = B A"
by (metis Un_commute Un_left_absorb)

type_synonym key = nat

consts
  all_symmetric :: bool        🍋 true if all keys are symmetric
  invKey        :: "key=>key"  🍋 inverse of a symmetric key

specification (invKey)
  invKey [simp]: "invKey (invKey K) = K"
  invKey_symmetric: "all_symmetric --> invKey = id"
by (metis id_apply)


textThe inverse of a symmetric key is itself; that of a public key
  is the private key and vice versa

definition symKeys :: "key set" where
  "symKeys == {K. invKey K = K}"

datatype  🍋 We allow any number of friendly agents
  agent = Server | Friend nat | Spy

datatype
     msg = Agent  agent     🍋 Agent names
         | Number nat       🍋 Ordinary integers, timestamps, ...
         | Nonce  nat       🍋 Unguessable nonces
         | Key    key       🍋 Crypto keys
         | Hash   msg       🍋 Hashing
         | MPair  msg msg   🍋 Compound messages
         | Crypt  key msg   🍋 Encryption, public- or shared-key


textConcrete syntax: messages appear as {A,B,NA}, etc...
syntax
  "_MTuple" :: "['a, args] ==> 'a * 'b"  ((indent=2 notation=mixfix message tuple\\{_,/ _}))
syntax_consts
  "_MTuple"  MPair
translations
  "{x, y, z}"  "{x, {y, z}}"
  "{x, y}"  "CONST MPair x y"


definition HPair :: "[msg,msg] => msg" ((4Hash[_] /_) [0, 1000]) where
    🍋 Message Y paired with a MAC computed with the help of X
    "Hash[X] Y == { Hash{X,Y}, Y}"

definition keysFor :: "msg set => key set" where
    🍋 Keys useful to decrypt elements of a message set
  "keysFor H == invKey ` {K. X. Crypt K X H}"


subsubsectionInductive Definition of All Parts" of a Message

inductive_set
  parts :: "msg set => msg set"
  for H :: "msg set"
  where
    Inj [intro]:               "X H ==> X parts H"
  | Fst:         "{X,Y} parts H ==> X parts H"
  | Snd:         "{X,Y} parts H ==> Y parts H"
  | Body:        "Crypt K X parts H ==> X parts H"

lemma parts_mono: "G H ==> parts(G) parts(H)"
apply auto
apply (erule parts.induct)
   apply (metis parts.Inj rev_subsetD)
  apply (metis parts.Fst)
 apply (metis parts.Snd)
by (metis parts.Body)

textEquations hold because constructors are injective.
lemma Friend_image_eq [simp]: "(Friend x Friend`A) = (xA)"
by (metis agent.inject image_iff)

lemma Key_image_eq [simp]: "(Key x Key`A) = (x A)"
by (metis image_iff msg.inject(4))

lemma Nonce_Key_image_eq [simp]: "Nonce x Key`A"
by (metis image_iff msg.distinct(23))


subsubsectionInverse of keys

lemma invKey_eq [simp]: "(invKey K = invKey K') = (K = K')"
by (metis invKey)


subsectionkeysFor operator

lemma keysFor_empty [simp]: "keysFor {} = {}"
by (unfold keysFor_def, blast)

lemma keysFor_Un [simp]: "keysFor (H H') = keysFor H keysFor H'"
by (unfold keysFor_def, blast)

lemma keysFor_UN [simp]: "keysFor (iA. H i) = (iA. keysFor (H i))"
by (unfold keysFor_def, blast)

textMonotonicity
lemma keysFor_mono: "G H ==> keysFor(G) keysFor(H)"
by (unfold keysFor_def, blast)

lemma keysFor_insert_Agent [simp]: "keysFor (insert (Agent A) H) = keysFor H"
by (unfold keysFor_def, auto)

lemma keysFor_insert_Nonce [simp]: "keysFor (insert (Nonce N) H) = keysFor H"
by (unfold keysFor_def, auto)

lemma keysFor_insert_Number [simp]: "keysFor (insert (Number N) H) = keysFor H"
by (unfold keysFor_def, auto)

lemma keysFor_insert_Key [simp]: "keysFor (insert (Key K) H) = keysFor H"
by (unfold keysFor_def, auto)

lemma keysFor_insert_Hash [simp]: "keysFor (insert (Hash X) H) = keysFor H"
by (unfold keysFor_def, auto)

lemma keysFor_insert_MPair [simp]: "keysFor (insert {X,Y} H) = keysFor H"
by (unfold keysFor_def, auto)

lemma keysFor_insert_Crypt [simp]:
    "keysFor (insert (Crypt K X) H) = insert (invKey K) (keysFor H)"
by (unfold keysFor_def, auto)

lemma keysFor_image_Key [simp]: "keysFor (Key`E) = {}"
by (unfold keysFor_def, auto)

lemma Crypt_imp_invKey_keysFor: "Crypt K X H ==> invKey K keysFor H"
by (unfold keysFor_def, blast)


subsectionInductive relation "parts"

lemma MPair_parts:
     "[| {X,Y} parts H;
         [| X parts H; Y parts H |] ==> P |] ==> P"
by (blast dest: parts.Fst parts.Snd)

declare MPair_parts [elim!] parts.Body [dest!]
textNB These two rules are UNSAFE in the formal sense, as they discard the
  compound message. They work well on THIS FILE.
  MPair_parts is left as SAFE because it speeds up proofs.
  The Crypt rule is normally kept UNSAFE to avoid breaking up certificates.

lemma parts_increasing: "H parts(H)"
by blast

lemmas parts_insertI = subset_insertI [THEN parts_mono, THEN subsetD]

lemma parts_empty [simp]: "parts{} = {}"
apply safe
apply (erule parts.induct)
apply blast+
done

lemma parts_emptyE [elim!]: "X parts{} ==> P"
by simp

textWARNING: loops if H = {Y}, therefore must not be repeated!
lemma parts_singleton: "X parts H ==> YH. X parts {Y}"
apply (erule parts.induct)
apply fast+
done


subsubsectionUnions

lemma parts_Un_subset1: "parts(G) parts(H) parts(G H)"
by (intro Un_least parts_mono Un_upper1 Un_upper2)

lemma parts_Un_subset2: "parts(G H) parts(G) parts(H)"
apply (rule subsetI)
apply (erule parts.induct, blast+)
done

lemma parts_Un [simp]: "parts(G H) = parts(G) parts(H)"
by (intro equalityI parts_Un_subset1 parts_Un_subset2)

lemma parts_insert: "parts (insert X H) = parts {X} parts H"
apply (subst insert_is_Un [of _ H])
apply (simp only: parts_Un)
done

lemma parts_insert2:
     "parts (insert X (insert Y H)) = parts {X} parts {Y} parts H"
by (metis Un_commute Un_empty_left Un_empty_right Un_insert_left Un_insert_right parts_Un)


lemma parts_UN_subset1: "(xA. parts(H x)) parts(xA. H x)"
by (intro UN_least parts_mono UN_upper)

lemma parts_UN_subset2: "parts(xA. H x) (xA. parts(H x))"
apply (rule subsetI)
apply (erule parts.induct, blast+)
done


textThis allows blast to simplify occurrences of
  🍋parts(GH) in the assumption.
lemmas in_parts_UnE = parts_Un [THEN equalityD1, THEN subsetD, THEN UnE]
declare in_parts_UnE [elim!]

lemma parts_insert_subset: "insert X (parts H) parts(insert X H)"
by (blast intro: parts_mono [THEN [2] rev_subsetD])

subsubsectionIdempotence and transitivity

lemma parts_partsD [dest!]: "X parts (parts H) ==> X parts H"
by (erule parts.induct, blast+)

lemma parts_idem [simp]: "parts (parts H) = parts H"
by blast

lemma parts_subset_iff [simp]: "(parts G parts H) = (G parts H)"
apply (rule iffI)
apply (metis Un_absorb1 Un_subset_iff parts_Un parts_increasing)
apply (metis parts_idem parts_mono)
done

lemma parts_trans: "[| X parts G; G parts H |] ==> X parts H"
by (blast dest: parts_mono)

lemma parts_cut: "[|Y parts (insert X G); X parts H|] ==> Y parts(G H)"
by (metis (no_types) Un_insert_left Un_insert_right insert_absorb le_supE
          parts_Un parts_idem parts_increasing parts_trans)

subsubsectionRewrite rules for pulling out atomic messages

lemmas parts_insert_eq_I = equalityI [OF subsetI parts_insert_subset]


lemma parts_insert_Agent [simp]:
     "parts (insert (Agent agt) H) = insert (Agent agt) (parts H)"
apply (rule parts_insert_eq_I)
apply (erule parts.induct, auto)
done

lemma parts_insert_Nonce [simp]:
     "parts (insert (Nonce N) H) = insert (Nonce N) (parts H)"
apply (rule parts_insert_eq_I)
apply (erule parts.induct, auto)
done

lemma parts_insert_Number [simp]:
     "parts (insert (Number N) H) = insert (Number N) (parts H)"
apply (rule parts_insert_eq_I)
apply (erule parts.induct, auto)
done

lemma parts_insert_Key [simp]:
     "parts (insert (Key K) H) = insert (Key K) (parts H)"
apply (rule parts_insert_eq_I)
apply (erule parts.induct, auto)
done

lemma parts_insert_Hash [simp]:
     "parts (insert (Hash X) H) = insert (Hash X) (parts H)"
apply (rule parts_insert_eq_I)
apply (erule parts.induct, auto)
done

lemma parts_insert_Crypt [simp]:
     "parts (insert (Crypt K X) H) =
          insert (Crypt K X) (parts (insert X H))"
apply (rule equalityI)
apply (rule subsetI)
apply (erule parts.induct, auto)
apply (blast intro: parts.Body)
done

lemma parts_insert_MPair [simp]:
     "parts (insert {X,Y} H) =
          insert {X,Y} (parts (insert X (insert Y H)))"
apply (rule equalityI)
apply (rule subsetI)
apply (erule parts.induct, auto)
apply (blast intro: parts.Fst parts.Snd)+
done

lemma parts_image_Key [simp]: "parts (Key`N) = Key`N"
apply auto
apply (erule parts.induct, auto)
done

lemma msg_Nonce_supply: "N. n. Nn --> Nonce n parts {msg}"
apply (induct_tac "msg")
apply (simp_all add: parts_insert2)
apply (metis Suc_n_not_le_n)
apply (metis le_trans linorder_linear)
done

subsectionInductive relation "analz"

textInductive definition of "analz" -- what can be broken down from a set of
  messages, including keys. A form of downward closure. Pairs can
  be taken apart; messages decrypted with known keys.

inductive_set
  analz :: "msg set => msg set"
  for H :: "msg set"
  where
    Inj [intro,simp] :    "X H ==> X analz H"
  | Fst:     "{X,Y} analz H ==> X analz H"
  | Snd:     "{X,Y} analz H ==> Y analz H"
  | Decrypt [dest]:
             "[|Crypt K X analz H; Key(invKey K) analz H|] ==> X analz H"


textMonotonicity; Lemma 1 of Lowe's paper
lemma analz_mono: "GH ==> analz(G) analz(H)"
apply auto
apply (erule analz.induct)
apply (auto dest: analz.Fst analz.Snd)
done

textMaking it safe speeds up proofs
lemma MPair_analz [elim!]:
     "[| {X,Y} analz H;
             [| X analz H; Y analz H |] ==> P
          |] ==> P"
by (blast dest: analz.Fst analz.Snd)

lemma analz_increasing: "H analz(H)"
by blast

lemma analz_subset_parts: "analz H parts H"
apply (rule subsetI)
apply (erule analz.induct, blast+)
done

lemmas analz_into_parts = analz_subset_parts [THEN subsetD]

lemmas not_parts_not_analz = analz_subset_parts [THEN contra_subsetD]

lemma parts_analz [simp]: "parts (analz H) = parts H"
apply (rule equalityI)
apply (metis analz_subset_parts parts_subset_iff)
apply (metis analz_increasing parts_mono)
done


lemma analz_parts [simp]: "analz (parts H) = parts H"
apply auto
apply (erule analz.induct, auto)
done

lemmas analz_insertI = subset_insertI [THEN analz_mono, THEN [2] rev_subsetD]

subsubsectionGeneral equational properties

lemma analz_empty [simp]: "analz{} = {}"
apply safe
apply (erule analz.induct, blast+)
done

textConverse fails: we can analz more from the union than from the
  separate parts, as a key in one might decrypt a message in the other
lemma analz_Un: "analz(G) analz(H) analz(G H)"
by (intro Un_least analz_mono Un_upper1 Un_upper2)

lemma analz_insert: "insert X (analz H) analz(insert X H)"
by (blast intro: analz_mono [THEN [2] rev_subsetD])

subsubsectionRewrite rules for pulling out atomic messages

lemmas analz_insert_eq_I = equalityI [OF subsetI analz_insert]

lemma analz_insert_Agent [simp]:
     "analz (insert (Agent agt) H) = insert (Agent agt) (analz H)"
apply (rule analz_insert_eq_I)
apply (erule analz.induct, auto)
done

lemma analz_insert_Nonce [simp]:
     "analz (insert (Nonce N) H) = insert (Nonce N) (analz H)"
apply (rule analz_insert_eq_I)
apply (erule analz.induct, auto)
done

lemma analz_insert_Number [simp]:
     "analz (insert (Number N) H) = insert (Number N) (analz H)"
apply (rule analz_insert_eq_I)
apply (erule analz.induct, auto)
done

lemma analz_insert_Hash [simp]:
     "analz (insert (Hash X) H) = insert (Hash X) (analz H)"
apply (rule analz_insert_eq_I)
apply (erule analz.induct, auto)
done

textCan only pull out Keys if they are not needed to decrypt the rest
lemma analz_insert_Key [simp]:
    "K keysFor (analz H) ==>
          analz (insert (Key K) H) = insert (Key K) (analz H)"
apply (unfold keysFor_def)
apply (rule analz_insert_eq_I)
apply (erule analz.induct, auto)
done

lemma analz_insert_MPair [simp]:
     "analz (insert {X,Y} H) =
          insert {X,Y} (analz (insert X (insert Y H)))"
apply (rule equalityI)
apply (rule subsetI)
apply (erule analz.induct, auto)
apply (erule analz.induct)
apply (blast intro: analz.Fst analz.Snd)+
done

textCan pull out enCrypted message if the Key is not known
lemma analz_insert_Crypt:
     "Key (invKey K) analz H
      ==> analz (insert (Crypt K X) H) = insert (Crypt K X) (analz H)"
apply (rule analz_insert_eq_I)
apply (erule analz.induct, auto)

done

lemma lemma1: "Key (invKey K) analz H ==>
               analz (insert (Crypt K X) H)
               insert (Crypt K X) (analz (insert X H))"
apply (rule subsetI)
apply (erule_tac x = x in analz.induct, auto)
done

lemma lemma2: "Key (invKey K) analz H ==>
               insert (Crypt K X) (analz (insert X H))
               analz (insert (Crypt K X) H)"
apply auto
apply (erule_tac x = x in analz.induct, auto)
apply (blast intro: analz_insertI analz.Decrypt)
done

lemma analz_insert_Decrypt:
     "Key (invKey K) analz H ==>
               analz (insert (Crypt K X) H) =
               insert (Crypt K X) (analz (insert X H))"
by (intro equalityI lemma1 lemma2)

textCase analysis: either the message is secure, or it is not! Effective,
 but can cause subgoals to blow up! Use with if_split; apparently
 split_tac does not cope with patterns such as 🍋analz (insert
 (Crypt K X) H)\
 lemma analz_Crypt_if [simp]:
  "analz (insert (Crypt K X) H) =
  (if (Key (invKey K) analz H)
  then insert (Crypt K X) (analz (insert X H))
  else insert (Crypt K X) (analz H))"
 by (simp add: analz_insert_Crypt analz_insert_Decrypt)
 
 
 textThis rule supposes "for the sake of argument" that we have the key.
 lemma analz_insert_Crypt_subset:
  "analz (insert (Crypt K X) H)
  insert (Crypt K X) (analz (insert X H))"
 apply (rule subsetI)
 apply (erule analz.induct, auto)
 done
 
 
 lemma analz_image_Key [simp]: "analz (Key`N) = Key`N"
 apply auto
 apply (erule analz.induct, auto)
 done
 
 
 subsubsectionIdempotence and transitivity
 
 lemma analz_analzD [dest!]: "X analz (analz H) ==> X analz H"
 by (erule analz.induct, blast+)
 
 lemma analz_idem [simp]: "analz (analz H) = analz H"
 by blast
 
 lemma analz_subset_iff [simp]: "(analz G analz H) = (G analz H)"
 apply (rule iffI)
 apply (iprover intro: subset_trans analz_increasing)
 apply (frule analz_mono, simp)
 done
 
 lemma analz_trans: "[| X analz G; G analz H |] ==> X analz H"
 by (drule analz_mono, blast)
 
 
 declare analz_trans[intro]
 
 lemma analz_cut: "[| Y analz (insert X H); X analz H |] ==> Y analz H"
 by (metis analz_idem analz_increasing analz_mono insert_absorb insert_mono insert_subset)
 
 textThis rewrite rule helps in the simplification of messages that involve
  the forwarding of unknown components (X). Without it, removing occurrences
  of X can be very complicated.
 lemma analz_insert_eq: "X analz H ==> analz (insert X H) = analz H"
 by (blast intro: analz_cut analz_insertI)
 
 
 textA congruence rule for "analz"
 
 lemma analz_subset_cong:
  "[| analz G analz G'; analz H analz H' |]
  ==> analz (G H) analz (G' H')"
 apply simp
 apply (metis Un_absorb2 Un_commute Un_subset_iff Un_upper1 Un_upper2 analz_mono)
 done
 
 
 lemma analz_cong:
  "[| analz G = analz G'; analz H = analz H'
  |] ==> analz (G H) = analz (G' H')"
 by (intro equalityI analz_subset_cong, simp_all)
 
 lemma analz_insert_cong:
  "analz H = analz H' ==> analz(insert X H) = analz(insert X H')"
 by (force simp only: insert_def intro!: analz_cong)
 
 textIf there are no pairs or encryptions then analz does nothing
 lemma analz_trivial:
  "[| X Y. {X,Y} H; X K. Crypt K X H |] ==> analz H = H"
 apply safe
 apply (erule analz.induct, blast+)
 done
 
 
 subsectionInductive relation "synth"
 
 textInductive definition of "synth" -- what can be built up from a set of
  messages. A form of upward closure. Pairs can be built, messages
  encrypted with known keys. Agent names are public domain.
  Numbers can be guessed, but Nonces cannot be.
 
 inductive_set
  synth :: "msg set => msg set"
  for H :: "msg set"
  where
  Inj [intro]: "X H ==> X synth H"
  | Agent [intro]: "Agent agt synth H"
  | Number [intro]: "Number n synth H"
  | Hash [intro]: "X synth H ==> Hash X synth H"
  | MPair [intro]: "[|X synth H; Y synth H|] ==> {X,Y} synth H"
  | Crypt [intro]: "[|X synth H; Key(K) H|] ==> Crypt K X synth H"
 
 textMonotonicity
 lemma synth_mono: "GH ==> synth(G) synth(H)"
  by (auto, erule synth.induct, auto)
 
 textNO Agent_synth, as any Agent name can be synthesized.
  The same holds for 🍋Number\
 inductive_cases Nonce_synth [elim!]: "Nonce n synth H"
 inductive_cases Key_synth [elim!]: "Key K synth H"
 inductive_cases Hash_synth [elim!]: "Hash X synth H"
 inductive_cases MPair_synth [elim!]: "{X,Y} synth H"
 inductive_cases Crypt_synth [elim!]: "Crypt K X synth H"
 
 
 lemma synth_increasing: "H synth(H)"
 by blast
 
 subsubsectionUnions
 
 textConverse fails: we can synth more from the union than from the
  separate parts, building a compound message using elements of each.
 lemma synth_Un: "synth(G) synth(H) synth(G H)"
 by (intro Un_least synth_mono Un_upper1 Un_upper2)
 
 lemma synth_insert: "insert X (synth H) synth(insert X H)"
 by (metis insert_iff insert_subset subset_insertI synth.Inj synth_mono)
 
 subsubsectionIdempotence and transitivity
 
 lemma synth_synthD [dest!]: "X synth (synth H) ==> X synth H"
 by (erule synth.induct, blast+)
 
 lemma synth_idem: "synth (synth H) = synth H"
 by blast
 
 lemma synth_subset_iff [simp]: "(synth G synth H) = (G synth H)"
 apply (rule iffI)
 apply (iprover intro: subset_trans synth_increasing)
 apply (frule synth_mono, simp add: synth_idem)
 done
 
 lemma synth_trans: "[| X synth G; G synth H |] ==> X synth H"
 by (drule synth_mono, blast)
 
 lemma synth_cut: "[| Y synth (insert X H); X synth H |] ==> Y synth H"
 by (metis insert_absorb insert_mono insert_subset synth_idem synth_increasing synth_mono)
 
 lemma Agent_synth [simp]: "Agent A synth H"
 by blast
 
 lemma Number_synth [simp]: "Number n synth H"
 by blast
 
 lemma Nonce_synth_eq [simp]: "(Nonce N synth H) = (Nonce N H)"
 by blast
 
 lemma Key_synth_eq [simp]: "(Key K synth H) = (Key K H)"
 by blast
 
 lemma Crypt_synth_eq [simp]:
  "Key K H ==> (Crypt K X synth H) = (Crypt K X H)"
 by blast
 
 
 lemma keysFor_synth [simp]:
  "keysFor (synth H) = keysFor H invKey`{K. Key K H}"
 by (unfold keysFor_def, blast)
 
 
 subsubsectionCombinations of parts, analz and synth
 
 lemma parts_synth [simp]: "parts (synth H) = parts H synth H"
 apply (rule equalityI)
 apply (rule subsetI)
 apply (erule parts.induct)
 apply (metis UnCI)
 apply (metis MPair_synth UnCI UnE insert_absorb insert_subset parts.Fst parts_increasing)
 apply (metis MPair_synth UnCI UnE insert_absorb insert_subset parts.Snd parts_increasing)
 apply (metis Body Crypt_synth UnCI UnE insert_absorb insert_subset parts_increasing)
 apply (metis Un_subset_iff parts_increasing parts_mono synth_increasing)
 done
 
 lemma analz_analz_Un [simp]: "analz (analz G H) = analz (G H)"
 apply (rule equalityI)
 apply (metis analz_idem analz_subset_cong order_eq_refl)
 apply (metis analz_increasing analz_subset_cong order_eq_refl)
 done
 
 declare analz_mono [intro] analz.Fst [intro] analz.Snd [intro] Un_least [intro]
 
 lemma analz_synth_Un [simp]: "analz (synth G H) = analz (G H) synth G"
 apply (rule equalityI)
 apply (rule subsetI)
 apply (erule analz.induct)
 apply (metis UnCI UnE Un_commute analz.Inj)
 apply (metis MPair_synth UnCI UnE Un_commute analz.Fst analz.Inj)
 apply (metis MPair_synth UnCI UnE Un_commute analz.Inj analz.Snd)
 apply (blast intro: analz.Decrypt)
 apply blast
 done
 
 lemma analz_synth [simp]: "analz (synth H) = analz H synth H"
 proof -
  have "x🪙2 x🪙1. synth x🪙1 analz (x🪙1 x🪙2) = analz (synth x🪙1 x🪙2)" by (metis Un_commute analz_synth_Un)
  hence "x🪙1. synth x🪙1 analz x🪙1 = analz (synth x🪙1 {})" by (metis Un_empty_right)
  hence "x🪙1. synth x🪙1 analz x🪙1 = analz (synth x🪙1)" by (metis Un_empty_right)
  hence "x🪙1. analz x🪙1 synth x🪙1 = analz (synth x🪙1)" by (metis Un_commute)
  thus "analz (synth H) = analz H synth H" by metis
 qed
 
 
 subsubsectionFor reasoning about the Fake rule in traces
 
 lemma parts_insert_subset_Un: "X G ==> parts(insert X H) parts G parts H"
 proof -
  assume "X G"
  hence "x🪙1. G x🪙1 X x🪙1 " by auto
  hence "x🪙1. X G x🪙1" by (metis Un_upper1)
  hence "insert X H G H" by (metis Un_upper2 insert_subset)
  hence "parts (insert X H) parts (G H)" by (metis parts_mono)
  thus "parts (insert X H) parts G parts H" by (metis parts_Un)
 qed
 
 lemma Fake_parts_insert:
  "X synth (analz H) ==>
  parts (insert X H) synth (analz H) parts H"
 proof -
  assume A1: "X synth (analz H)"
  have F1: "x🪙1. analz x🪙1 synth (analz x🪙1) = analz (synth (analz x🪙1))"
  by (metis analz_idem analz_synth)
  have F2: "x🪙1. parts x🪙1 synth (analz x🪙1) = parts (synth (analz x🪙1))"
  by (metis parts_analz parts_synth)
  have F3: "X synth (analz H)" using A1 by metis
  have "x🪙2 x🪙1::msg set. x🪙1 sup x🪙1 x🪙2" by (metis inf_sup_ord(3))
  hence F4: "x🪙1. analz x🪙1 analz (synth x🪙1)" by (metis analz_synth)
  have F5: "X synth (analz H)" using F3 by metis
  have "x🪙1. analz x🪙1 synth (analz x🪙1)
  analz (synth (analz x🪙1)) = synth (analz x🪙1)"
  using F1 by (metis subset_Un_eq)
  hence F6: "x🪙1. analz (synth (analz x🪙1)) = synth (analz x🪙1)"
  by (metis synth_increasing)
  have "x🪙1. x🪙1 analz (synth x🪙1)" using F4 by (metis analz_subset_iff)
  hence "x🪙1. x🪙1 analz (synth (analz x🪙1))" by (metis analz_subset_iff)
  hence "x🪙1. x🪙1 synth (analz x🪙1)" using F6 by metis
  hence "H synth (analz H)" by metis
  hence "H synth (analz H) X synth (analz H)" using F5 by metis
  hence "insert X H synth (analz H)" by (metis insert_subset)
  hence "parts (insert X H) parts (synth (analz H))" by (metis parts_mono)
  hence "parts (insert X H) parts H synth (analz H)" using F2 by metis
  thus "parts (insert X H) synth (analz H) parts H" by (metis Un_commute)
 qed
 
 lemma Fake_parts_insert_in_Un:
  "[|Z parts (insert X H); X synth (analz H)|]
  ==> Z synth (analz H) parts H"
 by (blast dest: Fake_parts_insert [THEN subsetD, dest])
 
 declare synth_mono [intro]
 
 lemma Fake_analz_insert:
  "X synth (analz G) ==>
  analz (insert X H) synth (analz G) analz (G H)"
 by (metis Un_commute Un_insert_left Un_insert_right Un_upper1 analz_analz_Un
  analz_mono analz_synth_Un insert_absorb)
 
 lemma Fake_analz_insert_simpler:
  "X synth (analz G) ==>
  analz (insert X H) synth (analz G) analz (G H)"
 apply (rule subsetI)
 apply (subgoal_tac "x analz (synth (analz G) H) ")
 apply (metis Un_commute analz_analz_Un analz_synth_Un)
 by (metis Un_upper1 Un_upper2 analz_mono insert_absorb insert_subset)
 
 end

Messung V0.5 in Prozent
C=53 H=47 G=50

¤ Dauer der Verarbeitung: 0.5 Sekunden  (vorverarbeitet am  2026-05-03) ¤

*© 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