src/HOL/Induct/QuoDataType.thy
author paulson
Thu, 02 Sep 2004 16:52:21 +0200
changeset 15172 73069e033a0b
parent 15169 2b5da07a0b89
child 16417 9bc16273c2d4
permissions -rw-r--r--
new example of a quotiented nested data type
     1 (*  Title:      HOL/Induct/QuoDataType
     2     ID:         $Id$
     3     Author:     Lawrence C Paulson, Cambridge University Computer Laboratory
     4     Copyright   2004  University of Cambridge
     5 
     6 *)
     7 
     8 header{*Defining an Initial Algebra by Quotienting a Free Algebra*}
     9 
    10 theory QuoDataType = Main:
    11 
    12 subsection{*Defining the Free Algebra*}
    13 
    14 text{*Messages with encryption and decryption as free constructors.*}
    15 datatype
    16      freemsg = NONCE  nat
    17 	     | MPAIR  freemsg freemsg
    18 	     | CRYPT  nat freemsg  
    19 	     | DECRYPT  nat freemsg
    20 
    21 text{*The equivalence relation, which makes encryption and decryption inverses
    22 provided the keys are the same.*}
    23 consts  msgrel :: "(freemsg * freemsg) set"
    24 
    25 syntax
    26   "_msgrel" :: "[freemsg, freemsg] => bool"  (infixl "~~" 50)
    27 syntax (xsymbols)
    28   "_msgrel" :: "[freemsg, freemsg] => bool"  (infixl "\<sim>" 50)
    29 syntax (HTML output)
    30   "_msgrel" :: "[freemsg, freemsg] => bool"  (infixl "\<sim>" 50)
    31 translations
    32   "X \<sim> Y" == "(X,Y) \<in> msgrel"
    33 
    34 text{*The first two rules are the desired equations. The next four rules
    35 make the equations applicable to subterms. The last two rules are symmetry
    36 and transitivity.*}
    37 inductive "msgrel"
    38   intros 
    39     CD:    "CRYPT K (DECRYPT K X) \<sim> X"
    40     DC:    "DECRYPT K (CRYPT K X) \<sim> X"
    41     NONCE: "NONCE N \<sim> NONCE N"
    42     MPAIR: "\<lbrakk>X \<sim> X'; Y \<sim> Y'\<rbrakk> \<Longrightarrow> MPAIR X Y \<sim> MPAIR X' Y'"
    43     CRYPT: "X \<sim> X' \<Longrightarrow> CRYPT K X \<sim> CRYPT K X'"
    44     DECRYPT: "X \<sim> X' \<Longrightarrow> DECRYPT K X \<sim> DECRYPT K X'"
    45     SYM:   "X \<sim> Y \<Longrightarrow> Y \<sim> X"
    46     TRANS: "\<lbrakk>X \<sim> Y; Y \<sim> Z\<rbrakk> \<Longrightarrow> X \<sim> Z"
    47 
    48 
    49 text{*Proving that it is an equivalence relation*}
    50 
    51 lemma msgrel_refl: "X \<sim> X"
    52 by (induct X, (blast intro: msgrel.intros)+)
    53 
    54 theorem equiv_msgrel: "equiv UNIV msgrel"
    55 proof (simp add: equiv_def, intro conjI)
    56   show "reflexive msgrel" by (simp add: refl_def msgrel_refl)
    57   show "sym msgrel" by (simp add: sym_def, blast intro: msgrel.SYM)
    58   show "trans msgrel" by (simp add: trans_def, blast intro: msgrel.TRANS)
    59 qed
    60 
    61 
    62 subsection{*Some Functions on the Free Algebra*}
    63 
    64 subsubsection{*The Set of Nonces*}
    65 
    66 text{*A function to return the set of nonces present in a message.  It will
    67 be lifted to the initial algrebra, to serve as an example of that process.*}
    68 consts
    69   freenonces :: "freemsg \<Rightarrow> nat set"
    70 
    71 primrec
    72    "freenonces (NONCE N) = {N}"
    73    "freenonces (MPAIR X Y) = freenonces X \<union> freenonces Y"
    74    "freenonces (CRYPT K X) = freenonces X"
    75    "freenonces (DECRYPT K X) = freenonces X"
    76 
    77 text{*This theorem lets us prove that the nonces function respects the
    78 equivalence relation.  It also helps us prove that Nonce
    79   (the abstract constructor) is injective*}
    80 theorem msgrel_imp_eq_freenonces: "U \<sim> V \<Longrightarrow> freenonces U = freenonces V"
    81 by (erule msgrel.induct, auto) 
    82 
    83 
    84 subsubsection{*The Left Projection*}
    85 
    86 text{*A function to return the left part of the top pair in a message.  It will
    87 be lifted to the initial algrebra, to serve as an example of that process.*}
    88 consts freeleft :: "freemsg \<Rightarrow> freemsg"
    89 primrec
    90    "freeleft (NONCE N) = NONCE N"
    91    "freeleft (MPAIR X Y) = X"
    92    "freeleft (CRYPT K X) = freeleft X"
    93    "freeleft (DECRYPT K X) = freeleft X"
    94 
    95 text{*This theorem lets us prove that the left function respects the
    96 equivalence relation.  It also helps us prove that MPair
    97   (the abstract constructor) is injective*}
    98 theorem msgrel_imp_eqv_freeleft:
    99      "U \<sim> V \<Longrightarrow> freeleft U \<sim> freeleft V"
   100 by (erule msgrel.induct, auto intro: msgrel.intros)
   101 
   102 
   103 subsubsection{*The Right Projection*}
   104 
   105 text{*A function to return the right part of the top pair in a message.*}
   106 consts freeright :: "freemsg \<Rightarrow> freemsg"
   107 primrec
   108    "freeright (NONCE N) = NONCE N"
   109    "freeright (MPAIR X Y) = Y"
   110    "freeright (CRYPT K X) = freeright X"
   111    "freeright (DECRYPT K X) = freeright X"
   112 
   113 text{*This theorem lets us prove that the right function respects the
   114 equivalence relation.  It also helps us prove that MPair
   115   (the abstract constructor) is injective*}
   116 theorem msgrel_imp_eqv_freeright:
   117      "U \<sim> V \<Longrightarrow> freeright U \<sim> freeright V"
   118 by (erule msgrel.induct, auto intro: msgrel.intros)
   119 
   120 
   121 subsubsection{*The Discriminator for Constructors*}
   122 
   123 text{*A function to distinguish nonces, mpairs and encryptions*}
   124 consts freediscrim :: "freemsg \<Rightarrow> int"
   125 primrec
   126    "freediscrim (NONCE N) = 0"
   127    "freediscrim (MPAIR X Y) = 1"
   128    "freediscrim (CRYPT K X) = freediscrim X + 2"
   129    "freediscrim (DECRYPT K X) = freediscrim X - 2"
   130 
   131 text{*This theorem helps us prove @{term "Nonce N \<noteq> MPair X Y"}*}
   132 theorem msgrel_imp_eq_freediscrim:
   133      "U \<sim> V \<Longrightarrow> freediscrim U = freediscrim V"
   134 by (erule msgrel.induct, auto)
   135 
   136 
   137 subsection{*The Initial Algebra: A Quotiented Message Type*}
   138 
   139 typedef (Msg)  msg = "UNIV//msgrel"
   140     by (auto simp add: quotient_def)
   141 
   142 
   143 text{*The abstract message constructors*}
   144 constdefs
   145   Nonce :: "nat \<Rightarrow> msg"
   146   "Nonce N == Abs_Msg(msgrel``{NONCE N})"
   147 
   148   MPair :: "[msg,msg] \<Rightarrow> msg"
   149    "MPair X Y ==
   150        Abs_Msg (\<Union>U \<in> Rep_Msg X. \<Union>V \<in> Rep_Msg Y. msgrel``{MPAIR U V})"
   151 
   152   Crypt :: "[nat,msg] \<Rightarrow> msg"
   153    "Crypt K X ==
   154        Abs_Msg (\<Union>U \<in> Rep_Msg X. msgrel``{CRYPT K U})"
   155 
   156   Decrypt :: "[nat,msg] \<Rightarrow> msg"
   157    "Decrypt K X ==
   158        Abs_Msg (\<Union>U \<in> Rep_Msg X. msgrel``{DECRYPT K U})"
   159 
   160 
   161 text{*Reduces equality of equivalence classes to the @{term msgrel} relation:
   162   @{term "(msgrel `` {x} = msgrel `` {y}) = ((x,y) \<in> msgrel)"} *}
   163 lemmas equiv_msgrel_iff = eq_equiv_class_iff [OF equiv_msgrel UNIV_I UNIV_I]
   164 
   165 declare equiv_msgrel_iff [simp]
   166 
   167 
   168 text{*All equivalence classes belong to set of representatives*}
   169 lemma [simp]: "msgrel``{U} \<in> Msg"
   170 by (auto simp add: Msg_def quotient_def intro: msgrel_refl)
   171 
   172 lemma inj_on_Abs_Msg: "inj_on Abs_Msg Msg"
   173 apply (rule inj_on_inverseI)
   174 apply (erule Abs_Msg_inverse)
   175 done
   176 
   177 text{*Reduces equality on abstractions to equality on representatives*}
   178 declare inj_on_Abs_Msg [THEN inj_on_iff, simp]
   179 
   180 declare Abs_Msg_inverse [simp]
   181 
   182 
   183 subsubsection{*Characteristic Equations for the Abstract Constructors*}
   184 
   185 lemma MPair: "MPair (Abs_Msg(msgrel``{U})) (Abs_Msg(msgrel``{V})) = 
   186               Abs_Msg (msgrel``{MPAIR U V})"
   187 proof -
   188   have "(\<lambda>U V. msgrel `` {MPAIR U V}) respects2 msgrel"
   189     by (simp add: congruent2_def msgrel.MPAIR)
   190   thus ?thesis
   191     by (simp add: MPair_def UN_equiv_class2 [OF equiv_msgrel equiv_msgrel])
   192 qed
   193 
   194 lemma Crypt: "Crypt K (Abs_Msg(msgrel``{U})) = Abs_Msg (msgrel``{CRYPT K U})"
   195 proof -
   196   have "(\<lambda>U. msgrel `` {CRYPT K U}) respects msgrel"
   197     by (simp add: congruent_def msgrel.CRYPT)
   198   thus ?thesis
   199     by (simp add: Crypt_def UN_equiv_class [OF equiv_msgrel])
   200 qed
   201 
   202 lemma Decrypt:
   203      "Decrypt K (Abs_Msg(msgrel``{U})) = Abs_Msg (msgrel``{DECRYPT K U})"
   204 proof -
   205   have "(\<lambda>U. msgrel `` {DECRYPT K U}) respects msgrel"
   206     by (simp add: congruent_def msgrel.DECRYPT)
   207   thus ?thesis
   208     by (simp add: Decrypt_def UN_equiv_class [OF equiv_msgrel])
   209 qed
   210 
   211 text{*Case analysis on the representation of a msg as an equivalence class.*}
   212 lemma eq_Abs_Msg [case_names Abs_Msg, cases type: msg]:
   213      "(!!U. z = Abs_Msg(msgrel``{U}) ==> P) ==> P"
   214 apply (rule Rep_Msg [of z, unfolded Msg_def, THEN quotientE])
   215 apply (drule arg_cong [where f=Abs_Msg])
   216 apply (auto simp add: Rep_Msg_inverse intro: msgrel_refl)
   217 done
   218 
   219 text{*Establishing these two equations is the point of the whole exercise*}
   220 theorem CD_eq [simp]: "Crypt K (Decrypt K X) = X"
   221 by (cases X, simp add: Crypt Decrypt CD)
   222 
   223 theorem DC_eq [simp]: "Decrypt K (Crypt K X) = X"
   224 by (cases X, simp add: Crypt Decrypt DC)
   225 
   226 
   227 subsection{*The Abstract Function to Return the Set of Nonces*}
   228 
   229 constdefs
   230   nonces :: "msg \<Rightarrow> nat set"
   231    "nonces X == \<Union>U \<in> Rep_Msg X. freenonces U"
   232 
   233 lemma nonces_congruent: "freenonces respects msgrel"
   234 by (simp add: congruent_def msgrel_imp_eq_freenonces) 
   235 
   236 
   237 text{*Now prove the four equations for @{term nonces}*}
   238 
   239 lemma nonces_Nonce [simp]: "nonces (Nonce N) = {N}"
   240 by (simp add: nonces_def Nonce_def 
   241               UN_equiv_class [OF equiv_msgrel nonces_congruent]) 
   242  
   243 lemma nonces_MPair [simp]: "nonces (MPair X Y) = nonces X \<union> nonces Y"
   244 apply (cases X, cases Y) 
   245 apply (simp add: nonces_def MPair 
   246                  UN_equiv_class [OF equiv_msgrel nonces_congruent]) 
   247 done
   248 
   249 lemma nonces_Crypt [simp]: "nonces (Crypt K X) = nonces X"
   250 apply (cases X) 
   251 apply (simp add: nonces_def Crypt
   252                  UN_equiv_class [OF equiv_msgrel nonces_congruent]) 
   253 done
   254 
   255 lemma nonces_Decrypt [simp]: "nonces (Decrypt K X) = nonces X"
   256 apply (cases X) 
   257 apply (simp add: nonces_def Decrypt
   258                  UN_equiv_class [OF equiv_msgrel nonces_congruent]) 
   259 done
   260 
   261 
   262 subsection{*The Abstract Function to Return the Left Part*}
   263 
   264 constdefs
   265   left :: "msg \<Rightarrow> msg"
   266    "left X == Abs_Msg (\<Union>U \<in> Rep_Msg X. msgrel``{freeleft U})"
   267 
   268 lemma left_congruent: "(\<lambda>U. msgrel `` {freeleft U}) respects msgrel"
   269 by (simp add: congruent_def msgrel_imp_eqv_freeleft) 
   270 
   271 text{*Now prove the four equations for @{term left}*}
   272 
   273 lemma left_Nonce [simp]: "left (Nonce N) = Nonce N"
   274 by (simp add: left_def Nonce_def 
   275               UN_equiv_class [OF equiv_msgrel left_congruent]) 
   276 
   277 lemma left_MPair [simp]: "left (MPair X Y) = X"
   278 apply (cases X, cases Y) 
   279 apply (simp add: left_def MPair 
   280                  UN_equiv_class [OF equiv_msgrel left_congruent]) 
   281 done
   282 
   283 lemma left_Crypt [simp]: "left (Crypt K X) = left X"
   284 apply (cases X) 
   285 apply (simp add: left_def Crypt
   286                  UN_equiv_class [OF equiv_msgrel left_congruent]) 
   287 done
   288 
   289 lemma left_Decrypt [simp]: "left (Decrypt K X) = left X"
   290 apply (cases X) 
   291 apply (simp add: left_def Decrypt
   292                  UN_equiv_class [OF equiv_msgrel left_congruent]) 
   293 done
   294 
   295 
   296 subsection{*The Abstract Function to Return the Right Part*}
   297 
   298 constdefs
   299   right :: "msg \<Rightarrow> msg"
   300    "right X == Abs_Msg (\<Union>U \<in> Rep_Msg X. msgrel``{freeright U})"
   301 
   302 lemma right_congruent: "(\<lambda>U. msgrel `` {freeright U}) respects msgrel"
   303 by (simp add: congruent_def msgrel_imp_eqv_freeright) 
   304 
   305 text{*Now prove the four equations for @{term right}*}
   306 
   307 lemma right_Nonce [simp]: "right (Nonce N) = Nonce N"
   308 by (simp add: right_def Nonce_def 
   309               UN_equiv_class [OF equiv_msgrel right_congruent]) 
   310 
   311 lemma right_MPair [simp]: "right (MPair X Y) = Y"
   312 apply (cases X, cases Y) 
   313 apply (simp add: right_def MPair 
   314                  UN_equiv_class [OF equiv_msgrel right_congruent]) 
   315 done
   316 
   317 lemma right_Crypt [simp]: "right (Crypt K X) = right X"
   318 apply (cases X) 
   319 apply (simp add: right_def Crypt
   320                  UN_equiv_class [OF equiv_msgrel right_congruent]) 
   321 done
   322 
   323 lemma right_Decrypt [simp]: "right (Decrypt K X) = right X"
   324 apply (cases X) 
   325 apply (simp add: right_def Decrypt
   326                  UN_equiv_class [OF equiv_msgrel right_congruent]) 
   327 done
   328 
   329 
   330 subsection{*Injectivity Properties of Some Constructors*}
   331 
   332 lemma NONCE_imp_eq: "NONCE m \<sim> NONCE n \<Longrightarrow> m = n"
   333 by (drule msgrel_imp_eq_freenonces, simp)
   334 
   335 text{*Can also be proved using the function @{term nonces}*}
   336 lemma Nonce_Nonce_eq [iff]: "(Nonce m = Nonce n) = (m = n)"
   337 by (auto simp add: Nonce_def msgrel_refl dest: NONCE_imp_eq)
   338 
   339 lemma MPAIR_imp_eqv_left: "MPAIR X Y \<sim> MPAIR X' Y' \<Longrightarrow> X \<sim> X'"
   340 by (drule msgrel_imp_eqv_freeleft, simp)
   341 
   342 lemma MPair_imp_eq_left: 
   343   assumes eq: "MPair X Y = MPair X' Y'" shows "X = X'"
   344 proof -
   345   from eq
   346   have "left (MPair X Y) = left (MPair X' Y')" by simp
   347   thus ?thesis by simp
   348 qed
   349 
   350 lemma MPAIR_imp_eqv_right: "MPAIR X Y \<sim> MPAIR X' Y' \<Longrightarrow> Y \<sim> Y'"
   351 by (drule msgrel_imp_eqv_freeright, simp)
   352 
   353 lemma MPair_imp_eq_right: "MPair X Y = MPair X' Y' \<Longrightarrow> Y = Y'" 
   354 apply (cases X, cases X', cases Y, cases Y') 
   355 apply (simp add: MPair)
   356 apply (erule MPAIR_imp_eqv_right)  
   357 done
   358 
   359 theorem MPair_MPair_eq [iff]: "(MPair X Y = MPair X' Y') = (X=X' & Y=Y')" 
   360 by (blast dest: MPair_imp_eq_left MPair_imp_eq_right)
   361 
   362 lemma NONCE_neqv_MPAIR: "NONCE m \<sim> MPAIR X Y \<Longrightarrow> False"
   363 by (drule msgrel_imp_eq_freediscrim, simp)
   364 
   365 theorem Nonce_neq_MPair [iff]: "Nonce N \<noteq> MPair X Y"
   366 apply (cases X, cases Y) 
   367 apply (simp add: Nonce_def MPair) 
   368 apply (blast dest: NONCE_neqv_MPAIR) 
   369 done
   370 
   371 text{*Example suggested by a referee*}
   372 theorem Crypt_Nonce_neq_Nonce: "Crypt K (Nonce M) \<noteq> Nonce N" 
   373 by (auto simp add: Nonce_def Crypt dest: msgrel_imp_eq_freediscrim)  
   374 
   375 text{*...and many similar results*}
   376 theorem Crypt2_Nonce_neq_Nonce: "Crypt K (Crypt K' (Nonce M)) \<noteq> Nonce N" 
   377 by (auto simp add: Nonce_def Crypt dest: msgrel_imp_eq_freediscrim)  
   378 
   379 theorem Crypt_Crypt_eq [iff]: "(Crypt K X = Crypt K X') = (X=X')" 
   380 proof
   381   assume "Crypt K X = Crypt K X'"
   382   hence "Decrypt K (Crypt K X) = Decrypt K (Crypt K X')" by simp
   383   thus "X = X'" by simp
   384 next
   385   assume "X = X'"
   386   thus "Crypt K X = Crypt K X'" by simp
   387 qed
   388 
   389 theorem Decrypt_Decrypt_eq [iff]: "(Decrypt K X = Decrypt K X') = (X=X')" 
   390 proof
   391   assume "Decrypt K X = Decrypt K X'"
   392   hence "Crypt K (Decrypt K X) = Crypt K (Decrypt K X')" by simp
   393   thus "X = X'" by simp
   394 next
   395   assume "X = X'"
   396   thus "Decrypt K X = Decrypt K X'" by simp
   397 qed
   398 
   399 lemma msg_induct [case_names Nonce MPair Crypt Decrypt, cases type: msg]:
   400   assumes N: "\<And>N. P (Nonce N)"
   401       and M: "\<And>X Y. \<lbrakk>P X; P Y\<rbrakk> \<Longrightarrow> P (MPair X Y)"
   402       and C: "\<And>K X. P X \<Longrightarrow> P (Crypt K X)"
   403       and D: "\<And>K X. P X \<Longrightarrow> P (Decrypt K X)"
   404   shows "P msg"
   405 proof (cases msg, erule ssubst)  
   406   fix U::freemsg
   407   show "P (Abs_Msg (msgrel `` {U}))"
   408   proof (induct U)
   409     case (NONCE N) 
   410     with N show ?case by (simp add: Nonce_def) 
   411   next
   412     case (MPAIR X Y)
   413     with M [of "Abs_Msg (msgrel `` {X})" "Abs_Msg (msgrel `` {Y})"]
   414     show ?case by (simp add: MPair) 
   415   next
   416     case (CRYPT K X)
   417     with C [of "Abs_Msg (msgrel `` {X})"]
   418     show ?case by (simp add: Crypt) 
   419   next
   420     case (DECRYPT K X)
   421     with D [of "Abs_Msg (msgrel `` {X})"]
   422     show ?case by (simp add: Decrypt)
   423   qed
   424 qed
   425 
   426 
   427 subsection{*The Abstract Discriminator*}
   428 
   429 text{*However, as @{text Crypt_Nonce_neq_Nonce} above illustrates, we don't
   430 need this function in order to prove discrimination theorems.*}
   431 
   432 constdefs
   433   discrim :: "msg \<Rightarrow> int"
   434    "discrim X == contents (\<Union>U \<in> Rep_Msg X. {freediscrim U})"
   435 
   436 lemma discrim_congruent: "(\<lambda>U. {freediscrim U}) respects msgrel"
   437 by (simp add: congruent_def msgrel_imp_eq_freediscrim) 
   438 
   439 text{*Now prove the four equations for @{term discrim}*}
   440 
   441 lemma discrim_Nonce [simp]: "discrim (Nonce N) = 0"
   442 by (simp add: discrim_def Nonce_def 
   443               UN_equiv_class [OF equiv_msgrel discrim_congruent]) 
   444 
   445 lemma discrim_MPair [simp]: "discrim (MPair X Y) = 1"
   446 apply (cases X, cases Y) 
   447 apply (simp add: discrim_def MPair 
   448                  UN_equiv_class [OF equiv_msgrel discrim_congruent]) 
   449 done
   450 
   451 lemma discrim_Crypt [simp]: "discrim (Crypt K X) = discrim X + 2"
   452 apply (cases X) 
   453 apply (simp add: discrim_def Crypt
   454                  UN_equiv_class [OF equiv_msgrel discrim_congruent]) 
   455 done
   456 
   457 lemma discrim_Decrypt [simp]: "discrim (Decrypt K X) = discrim X - 2"
   458 apply (cases X) 
   459 apply (simp add: discrim_def Decrypt
   460                  UN_equiv_class [OF equiv_msgrel discrim_congruent]) 
   461 done
   462 
   463 
   464 end
   465