(***************************************************************************** * Featherweight-OCL --- A Formal Semantics for UML-OCL Version OCL 2.5 * for the OMG Standard. * http://www.brucker.ch/projects/hol-testgen/ * * UML_State.thy --- State Operations and Objects. * This file is part of HOL-TestGen. * * Copyright (c) 2012-2015 Université Paris-Saclay, Univ. Paris-Sud, France * 2013-2015 IRT SystemX, France * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * * Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************) chapter\Formalization III: UML/OCL constructs: State Operations and Objects\ theory UML_State imports UML_Library begin no_notation None ("\") section\Introduction: States over Typed Object Universes\ text\\label{sec:universe} In the following, we will refine the concepts of a user-defined data-model (implied by a class-diagram) as well as the notion of $\state{}$ used in the previous section to much more detail. Surprisingly, even without a concrete notion of an objects and a universe of object representation, the generic infrastructure of state-related operations is fairly rich. \ subsection\Fundamental Properties on Objects: Core Referential Equality\ subsubsection\Definition\ text\Generic referential equality - to be used for instantiations with concrete object types ...\ definition StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t :: "('\,'a::{object,null})val \ ('\,'a)val \ ('\)Boolean" where "StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t x y \ \ \. if (\ x) \ = true \ \ (\ y) \ = true \ then if x \ = null \ y \ = null then \\x \ = null \ y \ = null\\ else \\(oid_of (x \)) = (oid_of (y \)) \\ else invalid \" subsubsection\Strictness and context passing\ lemma StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_strict1[simp,code_unfold] : "(StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t x invalid) = invalid" by(rule ext, simp add: StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def true_def false_def) lemma StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_strict2[simp,code_unfold] : "(StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t invalid x) = invalid" by(rule ext, simp add: StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def true_def false_def) lemma cp_StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t: "(StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t x y \) = (StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t (\_. x \) (\_. y \)) \" by(auto simp: StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def cp_valid[symmetric]) text_raw\\isatagafp\ lemmas cp0_StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t= cp_StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t[THEN allI[THEN allI[THEN allI[THEN cpI2]], of "StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t"]] lemmas cp_intro''[intro!,simp,code_unfold] = cp_intro'' cp_StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t[THEN allI[THEN allI[THEN allI[THEN cpI2]], of "StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t"]] text_raw\\endisatagafp\ subsection\Logic and Algebraic Layer on Object\ subsubsection\Validity and Definedness Properties\ text\We derive the usual laws on definedness for (generic) object equality:\ lemma StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_defargs: "\ \ (StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t x (y::('\,'a::{null,object})val))\ (\ \(\ x)) \ (\ \(\ y))" by(simp add: StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def OclValid_def true_def invalid_def bot_option_def split: bool.split_asm HOL.if_split_asm) lemma defined_StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_I: assumes val_x : "\ \ \ x" assumes val_x : "\ \ \ y" shows "\ \ \ (StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t x y)" apply(insert assms, simp add: StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def OclValid_def) by(subst cp_defined, simp add: true_def) lemma StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def_homo : "\(StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t x (y::('\,'a::{null,object})val)) = ((\ x) and (\ y))" oops (* sorry *) subsubsection\Symmetry\ lemma StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_sym : assumes x_val : "\ \ \ x" shows "\ \ StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t x x" by(simp add: StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def true_def OclValid_def x_val[simplified OclValid_def]) subsubsection\Behavior vs StrongEq\ text\It remains to clarify the role of the state invariant $\inv_\sigma(\sigma)$ mentioned above that states the condition that there is a ``one-to-one'' correspondence between object representations and $\oid$'s: $\forall \mathit{oid} \in \dom\ap \sigma\spot oid = \HolOclOidOf\ap \drop{\sigma(\mathit{oid})}$. This condition is also mentioned in~\cite[Annex A]{omg:ocl:2012} and goes back to \citet{richters:precise:2002}; however, we state this condition as an invariant on states rather than a global axiom. It can, therefore, not be taken for granted that an $\oid$ makes sense both in pre- and post-states of OCL expressions. \ text\We capture this invariant in the predicate WFF :\ definition WFF :: "('\::object)st \ bool" where "WFF \ = ((\ x \ ran(heap(fst \)). \heap(fst \) (oid_of x)\ = x) \ (\ x \ ran(heap(snd \)). \heap(snd \) (oid_of x)\ = x))" text\It turns out that WFF is a key-concept for linking strict referential equality to logical equality: in well-formed states (i.e. those states where the self (oid-of) field contains the pointer to which the object is associated to in the state), referential equality coincides with logical equality.\ text\We turn now to the generic definition of referential equality on objects: Equality on objects in a state is reduced to equality on the references to these objects. As in HOL-OCL~\cite{brucker.ea:hol-ocl:2008,brucker.ea:hol-ocl-book:2006}, we will store the reference of an object inside the object in a (ghost) field. By establishing certain invariants (``consistent state''), it can be assured that there is a ``one-to-one-correspondence'' of objects to their references---and therefore the definition below behaves as we expect.\ text\Generic Referential Equality enjoys the usual properties: (quasi) reflexivity, symmetry, transitivity, substitutivity for defined values. For type-technical reasons, for each concrete object type, the equality \\\ is defined by generic referential equality.\ theorem StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_vs_StrongEq: assumes WFF: "WFF \" and valid_x: "\ \(\ x)" and valid_y: "\ \(\ y)" and x_present_pre: "x \ \ ran (heap(fst \))" and y_present_pre: "y \ \ ran (heap(fst \))" and x_present_post:"x \ \ ran (heap(snd \))" and y_present_post:"y \ \ ran (heap(snd \))" (* x and y must be object representations that exist in either the pre or post state *) shows "(\ \ (StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t x y)) = (\ \ (x \ y))" apply(insert WFF valid_x valid_y x_present_pre y_present_pre x_present_post y_present_post) apply(auto simp: StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def OclValid_def WFF_def StrongEq_def true_def Ball_def) apply(erule_tac x="x \" in allE', simp_all) done theorem StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_vs_StrongEq': assumes WFF: "WFF \" and valid_x: "\ \(\ (x :: ('\::object,'\::{null,object})val))" and valid_y: "\ \(\ y)" and oid_preserve: "\x. x \ ran (heap(fst \)) \ x \ ran (heap(snd \)) \ H x \ \ \ oid_of (H x) = oid_of x" and xy_together: "x \ \ H ` ran (heap(fst \)) \ y \ \ H ` ran (heap(fst \)) \ x \ \ H ` ran (heap(snd \)) \ y \ \ H ` ran (heap(snd \))" (* x and y must be object representations that exist in either the pre or post state *) shows "(\ \ (StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t x y)) = (\ \ (x \ y))" apply(insert WFF valid_x valid_y xy_together) apply(simp add: WFF_def) apply(auto simp: StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def OclValid_def WFF_def StrongEq_def true_def Ball_def) by (metis foundation18' oid_preserve valid_x valid_y)+ text\So, if two object descriptions live in the same state (both pre or post), the referential equality on objects implies in a WFF state the logical equality.\ section\Operations on Object\ subsection\Initial States (for testing and code generation)\ definition \\<^sub>0 :: "('\)st" where "\\<^sub>0 \ (\heap=Map.empty, assocs = Map.empty\, \heap=Map.empty, assocs = Map.empty\)" subsection\OclAllInstances\ text\To denote OCL types occurring in OCL expressions syntactically---as, for example, as ``argument'' of \inlineocl{oclAllInstances()}---we use the inverses of the injection functions into the object universes; we show that this is a sufficient ``characterization.''\ definition OclAllInstances_generic :: "(('\::object) st \ '\ state) \ ('\::object \ '\) \ ('\, '\ option option) Set" where "OclAllInstances_generic fst_snd H = (\\. Abs_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e \\ Some ` ((H ` ran (heap (fst_snd \))) - { None }) \\)" lemma OclAllInstances_generic_defined: "\ \ \ (OclAllInstances_generic pre_post H)" apply(simp add: defined_def OclValid_def OclAllInstances_generic_def false_def true_def bot_fun_def bot_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e_def null_fun_def null_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e_def) apply(rule conjI) apply(rule notI, subst (asm) Abs_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e_inject, simp, (rule disjI2)+, metis bot_option_def option.distinct(1), (simp add: bot_option_def null_option_def)+)+ done lemma OclAllInstances_generic_init_empty: assumes [simp]: "\x. pre_post (x, x) = x" shows "\\<^sub>0 \ OclAllInstances_generic pre_post H \ Set{}" by(simp add: StrongEq_def OclAllInstances_generic_def OclValid_def \\<^sub>0_def mtSet_def) lemma represented_generic_objects_nonnull: assumes A: "\ \ ((OclAllInstances_generic pre_post (H::('\::object \ '\))) ->includes\<^sub>S\<^sub>e\<^sub>t(x))" shows "\ \ not(x \ null)" proof - have B: "\ \ \ (OclAllInstances_generic pre_post H)" by (simp add: OclAllInstances_generic_defined) have C: "\ \ \ x" by (metis OclIncludes.def_valid_then_def OclIncludes_valid_args_valid A foundation6) show ?thesis apply(insert A) apply(simp add: StrongEq_def OclValid_def OclNot_def null_def true_def OclIncludes_def B[simplified OclValid_def] C[simplified OclValid_def]) apply(simp add:OclAllInstances_generic_def) apply(erule contrapos_pn) apply(subst Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e.Abs_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e_inverse, auto simp: null_fun_def null_option_def bot_option_def) done qed lemma represented_generic_objects_defined: assumes A: "\ \ ((OclAllInstances_generic pre_post (H::('\::object \ '\))) ->includes\<^sub>S\<^sub>e\<^sub>t(x))" shows "\ \ \ (OclAllInstances_generic pre_post H) \ \ \ \ x" by (metis OclAllInstances_generic_defined A[THEN represented_generic_objects_nonnull] OclIncludes.defined_args_valid A foundation16' foundation18 foundation24 foundation6) text\One way to establish the actual presence of an object representation in a state is:\ definition "is_represented_in_state fst_snd x H \ = (x \ \ (Some o H) ` ran (heap (fst_snd \)))" lemma represented_generic_objects_in_state: assumes A: "\ \ (OclAllInstances_generic pre_post H)->includes\<^sub>S\<^sub>e\<^sub>t(x)" shows "is_represented_in_state pre_post x H \" proof - have B: "(\ (OclAllInstances_generic pre_post H)) \ = true \" by(simp add: OclValid_def[symmetric] OclAllInstances_generic_defined) have C: "(\ x) \ = true \" by (metis OclValid_def UML_Set.OclIncludes_def assms bot_option_def option.distinct(1) true_def) have F: "Rep_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e (Abs_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e \\Some ` (H ` ran (heap (pre_post \)) - {None})\\) = \\Some ` (H ` ran (heap (pre_post \)) - {None})\\" by(subst Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e.Abs_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e_inverse,simp_all add: bot_option_def) show ?thesis apply(insert A) apply(simp add: is_represented_in_state_def OclIncludes_def OclValid_def ran_def B C image_def true_def) apply(simp add: OclAllInstances_generic_def) apply(simp add: F) apply(simp add: ran_def) by(fastforce) qed lemma state_update_vs_allInstances_generic_empty: assumes [simp]: "\a. pre_post (mk a) = a" shows "(mk \heap=Map.empty, assocs=A\) \ OclAllInstances_generic pre_post Type \ Set{}" proof - have state_update_vs_allInstances_empty: "(OclAllInstances_generic pre_post Type) (mk \heap=Map.empty, assocs=A\) = Set{} (mk \heap=Map.empty, assocs=A\)" by(simp add: OclAllInstances_generic_def mtSet_def) show ?thesis apply(simp only: OclValid_def, subst StrictRefEq\<^sub>S\<^sub>e\<^sub>t.cp0, simp only: state_update_vs_allInstances_empty StrictRefEq\<^sub>S\<^sub>e\<^sub>t.refl_ext) apply(simp add: OclIf_def valid_def mtSet_def defined_def bot_fun_def null_fun_def null_option_def bot_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e_def) by(subst Abs_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e_inject, (simp add: bot_option_def true_def)+) qed text\Here comes a couple of operational rules that allow to infer the value of \inlineisar+oclAllInstances+ from the context $\tau$. These rules are a special-case in the sense that they are the only rules that relate statements with \emph{different} $\tau$'s. For that reason, new concepts like ``constant contexts P'' are necessary (for which we do not elaborate an own theory for reasons of space limitations; in examples, we will prove resulting constraints straight forward by hand).\ lemma state_update_vs_allInstances_generic_including': assumes [simp]: "\a. pre_post (mk a) = a" assumes "\x. \' oid = Some x \ x = Object" and "Type Object \ None" shows "(OclAllInstances_generic pre_post Type) (mk \heap=\'(oid\Object), assocs=A\) = ((OclAllInstances_generic pre_post Type)->including\<^sub>S\<^sub>e\<^sub>t(\ _. \\ drop (Type Object) \\)) (mk \heap=\',assocs=A\)" proof - have drop_none : "\x. x \ None \ \\x\\ = x" by(case_tac x, simp+) have insert_diff : "\x S. insert \x\ (S - {None}) = (insert \x\ S) - {None}" by (metis insert_Diff_if option.distinct(1) singletonE) show ?thesis apply(simp add: UML_Set.OclIncluding_def OclAllInstances_generic_defined[simplified OclValid_def], simp add: OclAllInstances_generic_def) apply(subst Abs_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e_inverse, simp add: bot_option_def, simp add: comp_def, subst image_insert[symmetric], subst drop_none, simp add: assms) apply(case_tac "Type Object", simp add: assms, simp only:, subst insert_diff, drule sym, simp) apply(subgoal_tac "ran (\'(oid \ Object)) = insert Object (ran \')", simp) apply(case_tac "\ (\x. \' oid = Some x)") apply(rule ran_map_upd, simp) apply(simp, erule exE, frule assms, simp) apply(subgoal_tac "Object \ ran \'") prefer 2 apply(rule ranI, simp) by(subst insert_absorb, simp, metis fun_upd_apply) qed lemma state_update_vs_allInstances_generic_including: assumes [simp]: "\a. pre_post (mk a) = a" assumes "\x. \' oid = Some x \ x = Object" and "Type Object \ None" shows "(OclAllInstances_generic pre_post Type) (mk \heap=\'(oid\Object), assocs=A\) = ((\_. (OclAllInstances_generic pre_post Type) (mk \heap=\', assocs=A\))->including\<^sub>S\<^sub>e\<^sub>t(\ _. \\ drop (Type Object) \\)) (mk \heap=\'(oid\Object), assocs=A\)" apply(subst state_update_vs_allInstances_generic_including', (simp add: assms)+, subst UML_Set.OclIncluding.cp0, simp add: UML_Set.OclIncluding_def) apply(subst (1 3) cp_defined[symmetric], simp add: OclAllInstances_generic_defined[simplified OclValid_def]) apply(simp add: defined_def OclValid_def OclAllInstances_generic_def invalid_def bot_fun_def null_fun_def bot_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e_def null_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e_def) apply(subst (1 3) Abs_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e_inject) by(simp add: bot_option_def null_option_def)+ lemma state_update_vs_allInstances_generic_noincluding': assumes [simp]: "\a. pre_post (mk a) = a" assumes "\x. \' oid = Some x \ x = Object" and "Type Object = None" shows "(OclAllInstances_generic pre_post Type) (mk \heap=\'(oid\Object), assocs=A\) = (OclAllInstances_generic pre_post Type) (mk \heap=\', assocs=A\)" proof - have drop_none : "\x. x \ None \ \\x\\ = x" by(case_tac x, simp+) have insert_diff : "\x S. insert \x\ (S - {None}) = (insert \x\ S) - {None}" by (metis insert_Diff_if option.distinct(1) singletonE) show ?thesis apply(simp add: OclIncluding_def OclAllInstances_generic_defined[simplified OclValid_def] OclAllInstances_generic_def) apply(subgoal_tac "ran (\'(oid \ Object)) = insert Object (ran \')", simp add: assms) apply(case_tac "\ (\x. \' oid = Some x)") apply(rule ran_map_upd, simp) apply(simp, erule exE, frule assms, simp) apply(subgoal_tac "Object \ ran \'") prefer 2 apply(rule ranI, simp) apply(subst insert_absorb, simp) by (metis fun_upd_apply) qed theorem state_update_vs_allInstances_generic_ntc: assumes [simp]: "\a. pre_post (mk a) = a" assumes oid_def: "oid\dom \'" and non_type_conform: "Type Object = None " and cp_ctxt: "cp P" and const_ctxt: "\X. const X \ const (P X)" shows "(mk \heap=\'(oid\Object),assocs=A\ \ P (OclAllInstances_generic pre_post Type)) = (mk \heap=\', assocs=A\ \ P (OclAllInstances_generic pre_post Type))" (is "(?\ \ P ?\) = (?\' \ P ?\)") proof - have P_cp : "\x \. P x \ = P (\_. x \) \" by (metis (full_types) cp_ctxt cp_def) have A : "const (P (\_. ?\ ?\))" by(simp add: const_ctxt const_ss) have "(?\ \ P ?\) = (?\ \ \_. P ?\ ?\)" by(subst foundation23, rule refl) also have "... = (?\ \ \_. P (\_. ?\ ?\) ?\)" by(subst P_cp, rule refl) also have "... = (?\' \ \_. P (\_. ?\ ?\) ?\')" apply(simp add: OclValid_def) by(subst A[simplified const_def], subst const_true[simplified const_def], simp) finally have X: "(?\ \ P ?\) = (?\' \ \_. P (\_. ?\ ?\) ?\')" by simp show ?thesis apply(subst X) apply(subst foundation23[symmetric]) apply(rule StrongEq_L_subst3[OF cp_ctxt]) apply(simp add: OclValid_def StrongEq_def true_def) apply(rule state_update_vs_allInstances_generic_noincluding') by(insert oid_def, auto simp: non_type_conform) qed theorem state_update_vs_allInstances_generic_tc: assumes [simp]: "\a. pre_post (mk a) = a" assumes oid_def: "oid\dom \'" and type_conform: "Type Object \ None " and cp_ctxt: "cp P" and const_ctxt: "\X. const X \ const (P X)" shows "(mk \heap=\'(oid\Object),assocs=A\ \ P (OclAllInstances_generic pre_post Type)) = (mk \heap=\', assocs=A\ \ P ((OclAllInstances_generic pre_post Type) ->including\<^sub>S\<^sub>e\<^sub>t(\ _. \(Type Object)\)))" (is "(?\ \ P ?\) = (?\' \ P ?\')") proof - have P_cp : "\x \. P x \ = P (\_. x \) \" by (metis (full_types) cp_ctxt cp_def) have A : "const (P (\_. ?\ ?\))" by(simp add: const_ctxt const_ss) have "(?\ \ P ?\) = (?\ \ \_. P ?\ ?\)" by(subst foundation23, rule refl) also have "... = (?\ \ \_. P (\_. ?\ ?\) ?\)" by(subst P_cp, rule refl) also have "... = (?\' \ \_. P (\_. ?\ ?\) ?\')" apply(simp add: OclValid_def) by(subst A[simplified const_def], subst const_true[simplified const_def], simp) finally have X: "(?\ \ P ?\) = (?\' \ \_. P (\_. ?\ ?\) ?\')" by simp let ?allInstances = "OclAllInstances_generic pre_post Type" have "?allInstances ?\ = \_. ?allInstances ?\'->including\<^sub>S\<^sub>e\<^sub>t(\_.\\\Type Object\\\) ?\" apply(rule state_update_vs_allInstances_generic_including) by(insert oid_def, auto simp: type_conform) also have "... = ((\_. ?allInstances ?\')->including\<^sub>S\<^sub>e\<^sub>t(\_. (\_.\\\Type Object\\\) ?\') ?\')" by(subst const_OclIncluding[simplified const_def], simp+) also have "... = (?allInstances->including\<^sub>S\<^sub>e\<^sub>t(\ _. \Type Object\) ?\')" apply(subst UML_Set.OclIncluding.cp0[symmetric]) by(insert type_conform, auto) finally have Y : "?allInstances ?\ = (?allInstances->including\<^sub>S\<^sub>e\<^sub>t(\ _. \Type Object\) ?\')" by auto show ?thesis apply(subst X) apply(subst foundation23[symmetric]) apply(rule StrongEq_L_subst3[OF cp_ctxt]) apply(simp add: OclValid_def StrongEq_def Y true_def) done qed declare OclAllInstances_generic_def [simp] subsubsection\OclAllInstances (@post)\ definition OclAllInstances_at_post :: "('\ :: object \ '\) \ ('\, '\ option option) Set" ("_ .allInstances'(')") where "OclAllInstances_at_post = OclAllInstances_generic snd" lemma OclAllInstances_at_post_defined: "\ \ \ (H .allInstances())" unfolding OclAllInstances_at_post_def by(rule OclAllInstances_generic_defined) lemma "\\<^sub>0 \ H .allInstances() \ Set{}" unfolding OclAllInstances_at_post_def by(rule OclAllInstances_generic_init_empty, simp) lemma represented_at_post_objects_nonnull: assumes A: "\ \ (((H::('\::object \ '\)).allInstances()) ->includes\<^sub>S\<^sub>e\<^sub>t(x))" shows "\ \ not(x \ null)" by(rule represented_generic_objects_nonnull[OF A[simplified OclAllInstances_at_post_def]]) lemma represented_at_post_objects_defined: assumes A: "\ \ (((H::('\::object \ '\)).allInstances()) ->includes\<^sub>S\<^sub>e\<^sub>t(x))" shows "\ \ \ (H .allInstances()) \ \ \ \ x" unfolding OclAllInstances_at_post_def by(rule represented_generic_objects_defined[OF A[simplified OclAllInstances_at_post_def]]) text\One way to establish the actual presence of an object representation in a state is:\ lemma assumes A: "\ \ H .allInstances()->includes\<^sub>S\<^sub>e\<^sub>t(x)" shows "is_represented_in_state snd x H \" by(rule represented_generic_objects_in_state[OF A[simplified OclAllInstances_at_post_def]]) lemma state_update_vs_allInstances_at_post_empty: shows "(\, \heap=Map.empty, assocs=A\) \ Type .allInstances() \ Set{}" unfolding OclAllInstances_at_post_def by(rule state_update_vs_allInstances_generic_empty[OF snd_conv]) text\Here comes a couple of operational rules that allow to infer the value of \inlineisar+oclAllInstances+ from the context $\tau$. These rules are a special-case in the sense that they are the only rules that relate statements with \emph{different} $\tau$'s. For that reason, new concepts like ``constant contexts P'' are necessary (for which we do not elaborate an own theory for reasons of space limitations; in examples, we will prove resulting constraints straight forward by hand).\ lemma state_update_vs_allInstances_at_post_including': assumes "\x. \' oid = Some x \ x = Object" and "Type Object \ None" shows "(Type .allInstances()) (\, \heap=\'(oid\Object), assocs=A\) = ((Type .allInstances())->including\<^sub>S\<^sub>e\<^sub>t(\ _. \\ drop (Type Object) \\)) (\, \heap=\',assocs=A\)" unfolding OclAllInstances_at_post_def by(rule state_update_vs_allInstances_generic_including'[OF snd_conv], insert assms) lemma state_update_vs_allInstances_at_post_including: assumes "\x. \' oid = Some x \ x = Object" and "Type Object \ None" shows "(Type .allInstances()) (\, \heap=\'(oid\Object), assocs=A\) = ((\_. (Type .allInstances()) (\, \heap=\', assocs=A\))->including\<^sub>S\<^sub>e\<^sub>t(\ _. \\ drop (Type Object) \\)) (\, \heap=\'(oid\Object), assocs=A\)" unfolding OclAllInstances_at_post_def by(rule state_update_vs_allInstances_generic_including[OF snd_conv], insert assms) lemma state_update_vs_allInstances_at_post_noincluding': assumes "\x. \' oid = Some x \ x = Object" and "Type Object = None" shows "(Type .allInstances()) (\, \heap=\'(oid\Object), assocs=A\) = (Type .allInstances()) (\, \heap=\', assocs=A\)" unfolding OclAllInstances_at_post_def by(rule state_update_vs_allInstances_generic_noincluding'[OF snd_conv], insert assms) theorem state_update_vs_allInstances_at_post_ntc: assumes oid_def: "oid\dom \'" and non_type_conform: "Type Object = None " and cp_ctxt: "cp P" and const_ctxt: "\X. const X \ const (P X)" shows "((\, \heap=\'(oid\Object),assocs=A\) \ (P(Type .allInstances()))) = ((\, \heap=\', assocs=A\) \ (P(Type .allInstances())))" unfolding OclAllInstances_at_post_def by(rule state_update_vs_allInstances_generic_ntc[OF snd_conv], insert assms) theorem state_update_vs_allInstances_at_post_tc: assumes oid_def: "oid\dom \'" and type_conform: "Type Object \ None " and cp_ctxt: "cp P" and const_ctxt: "\X. const X \ const (P X)" shows "((\, \heap=\'(oid\Object),assocs=A\) \ (P(Type .allInstances()))) = ((\, \heap=\', assocs=A\) \ (P((Type .allInstances()) ->including\<^sub>S\<^sub>e\<^sub>t(\ _. \(Type Object)\))))" unfolding OclAllInstances_at_post_def by(rule state_update_vs_allInstances_generic_tc[OF snd_conv], insert assms) subsubsection\OclAllInstances (@pre)\ definition OclAllInstances_at_pre :: "('\ :: object \ '\) \ ('\, '\ option option) Set" ("_ .allInstances@pre'(')") where "OclAllInstances_at_pre = OclAllInstances_generic fst" lemma OclAllInstances_at_pre_defined: "\ \ \ (H .allInstances@pre())" unfolding OclAllInstances_at_pre_def by(rule OclAllInstances_generic_defined) lemma "\\<^sub>0 \ H .allInstances@pre() \ Set{}" unfolding OclAllInstances_at_pre_def by(rule OclAllInstances_generic_init_empty, simp) lemma represented_at_pre_objects_nonnull: assumes A: "\ \ (((H::('\::object \ '\)).allInstances@pre()) ->includes\<^sub>S\<^sub>e\<^sub>t(x))" shows "\ \ not(x \ null)" by(rule represented_generic_objects_nonnull[OF A[simplified OclAllInstances_at_pre_def]]) lemma represented_at_pre_objects_defined: assumes A: "\ \ (((H::('\::object \ '\)).allInstances@pre()) ->includes\<^sub>S\<^sub>e\<^sub>t(x))" shows "\ \ \ (H .allInstances@pre()) \ \ \ \ x" unfolding OclAllInstances_at_pre_def by(rule represented_generic_objects_defined[OF A[simplified OclAllInstances_at_pre_def]]) text\One way to establish the actual presence of an object representation in a state is:\ lemma assumes A: "\ \ H .allInstances@pre()->includes\<^sub>S\<^sub>e\<^sub>t(x)" shows "is_represented_in_state fst x H \" by(rule represented_generic_objects_in_state[OF A[simplified OclAllInstances_at_pre_def]]) lemma state_update_vs_allInstances_at_pre_empty: shows "(\heap=Map.empty, assocs=A\, \) \ Type .allInstances@pre() \ Set{}" unfolding OclAllInstances_at_pre_def by(rule state_update_vs_allInstances_generic_empty[OF fst_conv]) text\Here comes a couple of operational rules that allow to infer the value of \inlineisar+oclAllInstances@pre+ from the context $\tau$. These rules are a special-case in the sense that they are the only rules that relate statements with \emph{different} $\tau$'s. For that reason, new concepts like ``constant contexts P'' are necessary (for which we do not elaborate an own theory for reasons of space limitations; in examples, we will prove resulting constraints straight forward by hand).\ lemma state_update_vs_allInstances_at_pre_including': assumes "\x. \' oid = Some x \ x = Object" and "Type Object \ None" shows "(Type .allInstances@pre()) (\heap=\'(oid\Object), assocs=A\, \) = ((Type .allInstances@pre())->including\<^sub>S\<^sub>e\<^sub>t(\ _. \\ drop (Type Object) \\)) (\heap=\',assocs=A\, \)" unfolding OclAllInstances_at_pre_def by(rule state_update_vs_allInstances_generic_including'[OF fst_conv], insert assms) lemma state_update_vs_allInstances_at_pre_including: assumes "\x. \' oid = Some x \ x = Object" and "Type Object \ None" shows "(Type .allInstances@pre()) (\heap=\'(oid\Object), assocs=A\, \) = ((\_. (Type .allInstances@pre()) (\heap=\', assocs=A\, \))->including\<^sub>S\<^sub>e\<^sub>t(\ _. \\ drop (Type Object) \\)) (\heap=\'(oid\Object), assocs=A\, \)" unfolding OclAllInstances_at_pre_def by(rule state_update_vs_allInstances_generic_including[OF fst_conv], insert assms) lemma state_update_vs_allInstances_at_pre_noincluding': assumes "\x. \' oid = Some x \ x = Object" and "Type Object = None" shows "(Type .allInstances@pre()) (\heap=\'(oid\Object), assocs=A\, \) = (Type .allInstances@pre()) (\heap=\', assocs=A\, \)" unfolding OclAllInstances_at_pre_def by(rule state_update_vs_allInstances_generic_noincluding'[OF fst_conv], insert assms) theorem state_update_vs_allInstances_at_pre_ntc: assumes oid_def: "oid\dom \'" and non_type_conform: "Type Object = None " and cp_ctxt: "cp P" and const_ctxt: "\X. const X \ const (P X)" shows "((\heap=\'(oid\Object),assocs=A\, \) \ (P(Type .allInstances@pre()))) = ((\heap=\', assocs=A\, \) \ (P(Type .allInstances@pre())))" unfolding OclAllInstances_at_pre_def by(rule state_update_vs_allInstances_generic_ntc[OF fst_conv], insert assms) theorem state_update_vs_allInstances_at_pre_tc: assumes oid_def: "oid\dom \'" and type_conform: "Type Object \ None " and cp_ctxt: "cp P" and const_ctxt: "\X. const X \ const (P X)" shows "((\heap=\'(oid\Object),assocs=A\, \) \ (P(Type .allInstances@pre()))) = ((\heap=\', assocs=A\, \) \ (P((Type .allInstances@pre()) ->including\<^sub>S\<^sub>e\<^sub>t(\ _. \(Type Object)\))))" unfolding OclAllInstances_at_pre_def by(rule state_update_vs_allInstances_generic_tc[OF fst_conv], insert assms) subsubsection\@post or @pre\ theorem StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_vs_StrongEq'': assumes WFF: "WFF \" and valid_x: "\ \(\ (x :: ('\::object,'\::object option option)val))" and valid_y: "\ \(\ y)" and oid_preserve: "\x. x \ ran (heap(fst \)) \ x \ ran (heap(snd \)) \ oid_of (H x) = oid_of x" and xy_together: "\ \ ((H .allInstances()->includes\<^sub>S\<^sub>e\<^sub>t(x) and H .allInstances()->includes\<^sub>S\<^sub>e\<^sub>t(y)) or (H .allInstances@pre()->includes\<^sub>S\<^sub>e\<^sub>t(x) and H .allInstances@pre()->includes\<^sub>S\<^sub>e\<^sub>t(y)))" (* x and y must be object representations that exist in either the pre or post state *) shows "(\ \ (StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t x y)) = (\ \ (x \ y))" proof - have at_post_def : "\x. \ \ \ x \ \ \ \ (H .allInstances()->includes\<^sub>S\<^sub>e\<^sub>t(x))" apply(simp add: OclIncludes_def OclValid_def OclAllInstances_at_post_defined[simplified OclValid_def]) by(subst cp_defined, simp) have at_pre_def : "\x. \ \ \ x \ \ \ \ (H .allInstances@pre()->includes\<^sub>S\<^sub>e\<^sub>t(x))" apply(simp add: OclIncludes_def OclValid_def OclAllInstances_at_pre_defined[simplified OclValid_def]) by(subst cp_defined, simp) have F: "Rep_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e (Abs_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e \\Some ` (H ` ran (heap (fst \)) - {None})\\) = \\Some ` (H ` ran (heap (fst \)) - {None})\\" by(subst Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e.Abs_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e_inverse,simp_all add: bot_option_def) have F': "Rep_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e (Abs_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e \\Some ` (H ` ran (heap (snd \)) - {None})\\) = \\Some ` (H ` ran (heap (snd \)) - {None})\\" by(subst Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e.Abs_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e_inverse,simp_all add: bot_option_def) show ?thesis apply(rule StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_vs_StrongEq'[OF WFF valid_x valid_y, where H = "Some o H"]) apply(subst oid_preserve[symmetric], simp, simp add: oid_of_option_def) apply(insert xy_together, subst (asm) foundation11, metis at_post_def defined_and_I valid_x valid_y, metis at_pre_def defined_and_I valid_x valid_y) apply(erule disjE) by(drule foundation5, simp add: OclAllInstances_at_pre_def OclAllInstances_at_post_def OclValid_def OclIncludes_def true_def F F' valid_x[simplified OclValid_def] valid_y[simplified OclValid_def] bot_option_def split: if_split_asm, simp add: comp_def image_def, fastforce)+ qed subsection\OclIsNew, OclIsDeleted, OclIsMaintained, OclIsAbsent\ definition OclIsNew:: "('\, '\::{null,object})val \ ('\)Boolean" ("(_).oclIsNew'(')") where "X .oclIsNew() \ (\\ . if (\ X) \ = true \ then \\oid_of (X \) \ dom(heap(fst \)) \ oid_of (X \) \ dom(heap(snd \))\\ else invalid \)" text\The following predicates --- which are not part of the OCL standard descriptions --- complete the goal of \inlineisar+oclIsNew+ by describing where an object belongs. \ definition OclIsDeleted:: "('\, '\::{null,object})val \ ('\)Boolean" ("(_).oclIsDeleted'(')") where "X .oclIsDeleted() \ (\\ . if (\ X) \ = true \ then \\oid_of (X \) \ dom(heap(fst \)) \ oid_of (X \) \ dom(heap(snd \))\\ else invalid \)" definition OclIsMaintained:: "('\, '\::{null,object})val \ ('\)Boolean"("(_).oclIsMaintained'(')") where "X .oclIsMaintained() \ (\\ . if (\ X) \ = true \ then \\oid_of (X \) \ dom(heap(fst \)) \ oid_of (X \) \ dom(heap(snd \))\\ else invalid \)" definition OclIsAbsent:: "('\, '\::{null,object})val \ ('\)Boolean" ("(_).oclIsAbsent'(')") where "X .oclIsAbsent() \ (\\ . if (\ X) \ = true \ then \\oid_of (X \) \ dom(heap(fst \)) \ oid_of (X \) \ dom(heap(snd \))\\ else invalid \)" lemma state_split : "\ \ \ X \ \ \ (X .oclIsNew()) \ \ \ (X .oclIsDeleted()) \ \ \ (X .oclIsMaintained()) \ \ \ (X .oclIsAbsent())" by(simp add: OclIsDeleted_def OclIsNew_def OclIsMaintained_def OclIsAbsent_def OclValid_def true_def, blast) lemma notNew_vs_others : "\ \ \ X \ (\ \ \ (X .oclIsNew())) = (\ \ (X .oclIsDeleted()) \ \ \ (X .oclIsMaintained()) \ \ \ (X .oclIsAbsent()))" by(simp add: OclIsDeleted_def OclIsNew_def OclIsMaintained_def OclIsAbsent_def OclNot_def OclValid_def true_def, blast) subsection\OclIsModifiedOnly\ subsubsection\Definition\ text\The following predicate---which is not part of the OCL standard---provides a simple, but powerful means to describe framing conditions. For any formal approach, be it animation of OCL contracts, test-case generation or die-hard theorem proving, the specification of the part of a system transition that \emph{does not change} is of primordial importance. The following operator establishes the equality between old and new objects in the state (provided that they exist in both states), with the exception of those objects.\ definition OclIsModifiedOnly ::"('\::object,'\::{null,object})Set \ '\ Boolean" ("_->oclIsModifiedOnly'(')") where "X->oclIsModifiedOnly() \ (\(\,\'). let X' = (oid_of ` \\Rep_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e(X(\,\'))\\); S = ((dom (heap \) \ dom (heap \')) - X') in if (\ X) (\,\') = true (\,\') \ (\x\\\Rep_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e(X(\,\'))\\. x \ null) then \\\ x \ S. (heap \) x = (heap \') x\\ else invalid (\,\'))" subsubsection\Execution with Invalid or Null or Null Element as Argument\ lemma "invalid->oclIsModifiedOnly() = invalid" by(simp add: OclIsModifiedOnly_def) lemma "null->oclIsModifiedOnly() = invalid" by(simp add: OclIsModifiedOnly_def) lemma assumes X_null : "\ \ X->includes\<^sub>S\<^sub>e\<^sub>t(null)" shows "\ \ X->oclIsModifiedOnly() \ invalid" apply(insert X_null, simp add : OclIncludes_def OclIsModifiedOnly_def StrongEq_def OclValid_def true_def) apply(case_tac \, simp) apply(simp split: if_split_asm) by(simp add: null_fun_def, blast) subsubsection\Context Passing\ lemma cp_OclIsModifiedOnly : "X->oclIsModifiedOnly() \ = (\_. X \)->oclIsModifiedOnly() \" by(simp only: OclIsModifiedOnly_def, case_tac \, simp only:, subst cp_defined, simp) subsection\OclSelf\ text\The following predicate---which is not part of the OCL standard---explicitly retrieves in the pre or post state the original OCL expression given as argument.\ definition [simp]: "OclSelf x H fst_snd = (\\ . if (\ x) \ = true \ then if oid_of (x \) \ dom(heap(fst \)) \ oid_of (x \) \ dom(heap (snd \)) then H \(heap(fst_snd \))(oid_of (x \))\ else invalid \ else invalid \)" definition OclSelf_at_pre :: "('\::object,'\::{null,object})val \ ('\ \ '\) \ ('\::object,'\::{null,object})val" ("(_)@pre(_)") where "x @pre H = OclSelf x H fst" definition OclSelf_at_post :: "('\::object,'\::{null,object})val \ ('\ \ '\) \ ('\::object,'\::{null,object})val" ("(_)@post(_)") where "x @post H = OclSelf x H snd" subsection\Framing Theorem\ lemma all_oid_diff: assumes def_x : "\ \ \ x" assumes def_X : "\ \ \ X" assumes def_X' : "\x. x \ \\Rep_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e (X \)\\ \ x \ null" defines "P \ (\a. not (StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t x a))" shows "(\ \ X->forAll\<^sub>S\<^sub>e\<^sub>t(a| P a)) = (oid_of (x \) \ oid_of ` \\Rep_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e (X \)\\)" proof - have P_null_bot: "\b. b = null \ b = \ \ \ (\x\\\Rep_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e (X \)\\. P (\(_:: 'a state \ 'a state). x) \ = b \)" apply(erule disjE) apply(simp, rule ballI, simp add: P_def StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def, rename_tac x', subst cp_OclNot, simp, subgoal_tac "x \ \ null \ x' \ null", simp, simp add: OclNot_def null_fun_def null_option_def bot_option_def bot_fun_def invalid_def, ( metis def_X' def_x foundation16[THEN iffD1] | (metis bot_fun_def OclValid_def Set_inv_lemma def_X def_x defined_def valid_def, metis def_X' def_x foundation16[THEN iffD1])))+ done have not_inj : "\x y. ((not x) \ = (not y) \) = (x \ = y \)" by (metis foundation21 foundation22) have P_false : "\x\\\Rep_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e (X \)\\. P (\_. x) \ = false \ \ oid_of (x \) \ oid_of ` \\Rep_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e (X \)\\" apply(erule bexE, rename_tac x') apply(simp add: P_def) apply(simp only: OclNot3[symmetric], simp only: not_inj) apply(simp add: StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def split: if_split_asm) apply(subgoal_tac "x \ \ null \ x' \ null", simp) apply (metis (mono_tags) drop.simps def_x foundation16[THEN iffD1] true_def) by(simp add: invalid_def bot_option_def true_def)+ have P_true : "\x\\\Rep_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e (X \)\\. P (\_. x) \ = true \ \ oid_of (x \) \ oid_of ` \\Rep_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e (X \)\\" apply(subgoal_tac "\x'\\\Rep_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e (X \)\\. oid_of x' \ oid_of (x \)") apply (metis imageE) apply(rule ballI, drule_tac x = "x'" in ballE) prefer 3 apply assumption apply(simp add: P_def) apply(simp only: OclNot4[symmetric], simp only: not_inj) apply(simp add: StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def false_def split: if_split_asm) apply(subgoal_tac "x \ \ null \ x' \ null", simp) apply (metis def_X' def_x foundation16[THEN iffD1]) by(simp add: invalid_def bot_option_def false_def)+ have bool_split : "\x\\\Rep_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e (X \)\\. P (\_. x) \ \ null \ \ \x\\\Rep_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e (X \)\\. P (\_. x) \ \ \ \ \ \x\\\Rep_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e (X \)\\. P (\_. x) \ \ false \ \ \x\\\Rep_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e (X \)\\. P (\_. x) \ = true \" apply(rule ballI) apply(drule_tac x = x in ballE) prefer 3 apply assumption apply(drule_tac x = x in ballE) prefer 3 apply assumption apply(drule_tac x = x in ballE) prefer 3 apply assumption apply (metis (full_types) bot_fun_def OclNot4 OclValid_def foundation16 foundation9 not_inj null_fun_def) by(fast+) show ?thesis apply(subst OclForall_rep_set_true[OF def_X], simp add: OclValid_def) apply(rule iffI, simp add: P_true) by (metis P_false P_null_bot bool_split) qed theorem framing: assumes modifiesclause:"\ \ (X->excluding\<^sub>S\<^sub>e\<^sub>t(x))->oclIsModifiedOnly()" and oid_is_typerepr : "\ \ X->forAll\<^sub>S\<^sub>e\<^sub>t(a| not (StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t x a))" shows "\ \ (x @pre P \ (x @post P))" apply(case_tac "\ \ \ x") proof - show "\ \ \ x \ ?thesis" proof - assume def_x : "\ \ \ x" show ?thesis proof - have def_X : "\ \ \ X" apply(insert oid_is_typerepr, simp add: UML_Set.OclForall_def OclValid_def split: if_split_asm) by(simp add: bot_option_def true_def) have def_X' : "\x. x \ \\Rep_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e (X \)\\ \ x \ null" apply(insert modifiesclause, simp add: OclIsModifiedOnly_def OclValid_def split: if_split_asm) apply(case_tac \, simp split: if_split_asm) apply(simp add: UML_Set.OclExcluding_def split: if_split_asm) apply(subst (asm) (2) Abs_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e_inverse) apply(simp, (rule disjI2)+) apply (metis (opaque_lifting, mono_tags) Diff_iff Set_inv_lemma def_X) apply(simp) apply(erule ballE[where P = "\x. x \ null"]) apply(assumption) apply(simp) apply (metis (opaque_lifting, no_types) def_x foundation16[THEN iffD1]) apply (metis (opaque_lifting, no_types) OclValid_def def_X def_x foundation20 OclExcluding_valid_args_valid OclExcluding_valid_args_valid'') by(simp add: invalid_def bot_option_def) have oid_is_typerepr : "oid_of (x \) \ oid_of ` \\Rep_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e (X \)\\" by(rule all_oid_diff[THEN iffD1, OF def_x def_X def_X' oid_is_typerepr]) show ?thesis apply(simp add: StrongEq_def OclValid_def true_def OclSelf_at_pre_def OclSelf_at_post_def def_x[simplified OclValid_def]) apply(rule conjI, rule impI) apply(rule_tac f = "\x. P \x\" in arg_cong) apply(insert modifiesclause[simplified OclIsModifiedOnly_def OclValid_def]) apply(case_tac \, rename_tac \ \', simp split: if_split_asm) apply(subst (asm) (2) UML_Set.OclExcluding_def) apply(drule foundation5[simplified OclValid_def true_def], simp) apply(subst (asm) Abs_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e_inverse, simp) apply(rule disjI2)+ apply (metis (opaque_lifting, no_types) DiffD1 OclValid_def Set_inv_lemma def_x foundation16 foundation18') apply(simp) apply(erule_tac x = "oid_of (x (\, \'))" in ballE) apply simp+ apply (metis (opaque_lifting, no_types) DiffD1 image_iff image_insert insert_Diff_single insert_absorb oid_is_typerepr) apply(simp add: invalid_def bot_option_def)+ by blast qed qed qed(simp add: OclSelf_at_post_def OclSelf_at_pre_def OclValid_def StrongEq_def true_def)+ text\As corollary, the framing property can be expressed with only the strong equality as comparison operator.\ theorem framing': assumes wff : "WFF \" assumes modifiesclause:"\ \ (X->excluding\<^sub>S\<^sub>e\<^sub>t(x))->oclIsModifiedOnly()" and oid_is_typerepr : "\ \ X->forAll\<^sub>S\<^sub>e\<^sub>t(a| not (x \ a))" and oid_preserve: "\x. x \ ran (heap(fst \)) \ x \ ran (heap(snd \)) \ oid_of (H x) = oid_of x" and xy_together: "\ \ X->forAll\<^sub>S\<^sub>e\<^sub>t(y | (H .allInstances()->includes\<^sub>S\<^sub>e\<^sub>t(x) and H .allInstances()->includes\<^sub>S\<^sub>e\<^sub>t(y)) or (H .allInstances@pre()->includes\<^sub>S\<^sub>e\<^sub>t(x) and H .allInstances@pre()->includes\<^sub>S\<^sub>e\<^sub>t(y)))" shows "\ \ (x @pre P \ (x @post P))" proof - have def_X : "\ \ \ X" apply(insert oid_is_typerepr, simp add: UML_Set.OclForall_def OclValid_def split: if_split_asm) by(simp add: bot_option_def true_def) show ?thesis apply(case_tac "\ \ \ x", drule foundation20) apply(rule framing[OF modifiesclause]) apply(rule OclForall_cong'[OF _ oid_is_typerepr xy_together], rename_tac y) apply(cut_tac Set_inv_lemma'[OF def_X]) prefer 2 apply assumption apply(rule OclNot_contrapos_nn, simp add: StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def) apply(simp add: OclValid_def, subst cp_defined, simp, assumption) apply(rule StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_vs_StrongEq''[THEN iffD1, OF wff _ _ oid_preserve], assumption+) by(simp add: OclSelf_at_post_def OclSelf_at_pre_def OclValid_def StrongEq_def true_def)+ qed subsection\Miscellaneous\ lemma pre_post_new: "\ \ (x .oclIsNew()) \ \ (\ \ \(x @pre H1)) \ \ (\ \ \(x @post H2))" by(simp add: OclIsNew_def OclSelf_at_pre_def OclSelf_at_post_def OclValid_def StrongEq_def true_def false_def bot_option_def invalid_def bot_fun_def valid_def split: if_split_asm) lemma pre_post_old: "\ \ (x .oclIsDeleted()) \ \ (\ \ \(x @pre H1)) \ \ (\ \ \(x @post H2))" by(simp add: OclIsDeleted_def OclSelf_at_pre_def OclSelf_at_post_def OclValid_def StrongEq_def true_def false_def bot_option_def invalid_def bot_fun_def valid_def split: if_split_asm) lemma pre_post_absent: "\ \ (x .oclIsAbsent()) \ \ (\ \ \(x @pre H1)) \ \ (\ \ \(x @post H2))" by(simp add: OclIsAbsent_def OclSelf_at_pre_def OclSelf_at_post_def OclValid_def StrongEq_def true_def false_def bot_option_def invalid_def bot_fun_def valid_def split: if_split_asm) lemma pre_post_maintained: "(\ \ \(x @pre H1) \ \ \ \(x @post H2)) \ \ \ (x .oclIsMaintained())" by(simp add: OclIsMaintained_def OclSelf_at_pre_def OclSelf_at_post_def OclValid_def StrongEq_def true_def false_def bot_option_def invalid_def bot_fun_def valid_def split: if_split_asm) lemma pre_post_maintained': "\ \ (x .oclIsMaintained()) \ (\ \ \(x @pre (Some o H1)) \ \ \ \(x @post (Some o H2)))" by(simp add: OclIsMaintained_def OclSelf_at_pre_def OclSelf_at_post_def OclValid_def StrongEq_def true_def false_def bot_option_def invalid_def bot_fun_def valid_def split: if_split_asm) lemma framing_same_state: "(\, \) \ (x @pre H \ (x @post H))" by(simp add: OclSelf_at_pre_def OclSelf_at_post_def OclValid_def StrongEq_def) section\Accessors on Object\ subsection\Definition\ definition "select_object mt incl smash deref l = smash (foldl incl mt (map deref l)) \ \smash returns null with \mt\ in input (in this case, object contains null pointer)\" text\The continuation \f\ is usually instantiated with a smashing function which is either the identity @{term id} or, for \inlineocl{0..1} cardinalities of associations, the @{term OclANY}-selector which also handles the @{term null}-cases appropriately. A standard use-case for this combinator is for example:\ term "(select_object mtSet UML_Set.OclIncluding UML_Set.OclANY f l oid )::('\, 'a::null)val" definition "select_object\<^sub>S\<^sub>e\<^sub>t = select_object mtSet UML_Set.OclIncluding id" definition "select_object_any0\<^sub>S\<^sub>e\<^sub>t f s_set = UML_Set.OclANY (select_object\<^sub>S\<^sub>e\<^sub>t f s_set)" definition "select_object_any\<^sub>S\<^sub>e\<^sub>t f s_set = (let s = select_object\<^sub>S\<^sub>e\<^sub>t f s_set in if s->size\<^sub>S\<^sub>e\<^sub>t() \ \ then s->any\<^sub>S\<^sub>e\<^sub>t() else \ endif)" definition "select_object\<^sub>S\<^sub>e\<^sub>q = select_object mtSequence UML_Sequence.OclIncluding id" definition "select_object_any\<^sub>S\<^sub>e\<^sub>q f s_set = UML_Sequence.OclANY (select_object\<^sub>S\<^sub>e\<^sub>q f s_set)" definition "select_object\<^sub>P\<^sub>a\<^sub>i\<^sub>r f1 f2 = (\(a,b). OclPair (f1 a) (f2 b))" subsection\Validity and Definedness Properties\ lemma select_fold_exec\<^sub>S\<^sub>e\<^sub>q: assumes "list_all (\f. (\ \ \ f)) l" shows "\\Rep_Sequence\<^sub>b\<^sub>a\<^sub>s\<^sub>e (foldl UML_Sequence.OclIncluding Sequence{} l \)\\ = List.map (\f. f \) l" proof - have def_fold: "\l. list_all (\f. \ \ \ f) l \ \ \ (\ foldl UML_Sequence.OclIncluding Sequence{} l)" apply(rule rev_induct[where P = "\l. list_all (\f. (\ \ \ f)) l \ \ \ (\ foldl UML_Sequence.OclIncluding Sequence{} l)", THEN mp], simp) by(simp add: foundation10') show ?thesis apply(rule rev_induct[where P = "\l. list_all (\f. (\ \ \ f)) l \ \\Rep_Sequence\<^sub>b\<^sub>a\<^sub>s\<^sub>e (foldl UML_Sequence.OclIncluding Sequence{} l \)\\ = List.map (\f. f \) l", THEN mp], simp) apply(simp add: mtSequence_def) apply(subst Abs_Sequence\<^sub>b\<^sub>a\<^sub>s\<^sub>e_inverse, (simp | intro impI)+) apply(simp add: UML_Sequence.OclIncluding_def, intro conjI impI) apply(subst Abs_Sequence\<^sub>b\<^sub>a\<^sub>s\<^sub>e_inverse, simp, (rule disjI2)+) apply(simp add: list_all_iff foundation18', simp) apply(subst (asm) def_fold[simplified (no_asm) OclValid_def], simp, simp add: OclValid_def) by (rule assms) qed lemma select_fold_exec\<^sub>S\<^sub>e\<^sub>t: assumes "list_all (\f. (\ \ \ f)) l" shows "\\Rep_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e (foldl UML_Set.OclIncluding Set{} l \)\\ = set (List.map (\f. f \) l)" proof - have def_fold: "\l. list_all (\f. \ \ \ f) l \ \ \ (\ foldl UML_Set.OclIncluding Set{} l)" apply(rule rev_induct[where P = "\l. list_all (\f. (\ \ \ f)) l \ \ \ (\ foldl UML_Set.OclIncluding Set{} l)", THEN mp], simp) by(simp add: foundation10') show ?thesis apply(rule rev_induct[where P = "\l. list_all (\f. (\ \ \ f)) l \ \\Rep_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e (foldl UML_Set.OclIncluding Set{} l \)\\ = set (List.map (\f. f \) l)", THEN mp], simp) apply(simp add: mtSet_def) apply(subst Abs_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e_inverse, (simp | intro impI)+) apply(simp add: UML_Set.OclIncluding_def, intro conjI impI) apply(subst Abs_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e_inverse, simp, (rule disjI2)+) apply(simp add: list_all_iff foundation18', simp) apply(subst (asm) def_fold[simplified (no_asm) OclValid_def], simp, simp add: OclValid_def) by (rule assms) qed lemma fold_val_elem\<^sub>S\<^sub>e\<^sub>q: assumes "\ \ \ (foldl UML_Sequence.OclIncluding Sequence{} (List.map (f p) s_set))" shows "list_all (\x. (\ \ \ (f p x))) s_set" apply(rule rev_induct[where P = "\s_set. \ \ \ foldl UML_Sequence.OclIncluding Sequence{} (List.map (f p) s_set) \ list_all (\x. \ \ \ f p x) s_set", THEN mp]) apply(simp, auto) apply (metis (opaque_lifting, mono_tags) UML_Sequence.OclIncluding.def_valid_then_def UML_Sequence.OclIncluding.defined_args_valid foundation20)+ by(simp add: assms) lemma fold_val_elem\<^sub>S\<^sub>e\<^sub>t: assumes "\ \ \ (foldl UML_Set.OclIncluding Set{} (List.map (f p) s_set))" shows "list_all (\x. (\ \ \ (f p x))) s_set" apply(rule rev_induct[where P = "\s_set. \ \ \ foldl UML_Set.OclIncluding Set{} (List.map (f p) s_set) \ list_all (\x. \ \ \ f p x) s_set", THEN mp]) apply(simp, auto) apply (metis (opaque_lifting, mono_tags) foundation10' foundation20)+ by(simp add: assms) lemma select_object_any_defined\<^sub>S\<^sub>e\<^sub>q: assumes def_sel: "\ \ \ (select_object_any\<^sub>S\<^sub>e\<^sub>q f s_set)" shows "s_set \ []" apply(insert def_sel, case_tac s_set) apply(simp add: select_object_any\<^sub>S\<^sub>e\<^sub>q_def UML_Sequence.OclANY_def select_object\<^sub>S\<^sub>e\<^sub>q_def select_object_def defined_def OclValid_def false_def true_def bot_fun_def bot_option_def split: if_split_asm) apply(simp add: mtSequence_def, subst (asm) Abs_Sequence\<^sub>b\<^sub>a\<^sub>s\<^sub>e_inverse, simp, simp) by(simp) lemma (*select_object_any_defined\<^sub>S\<^sub>e\<^sub>t:*) assumes def_sel: "\ \ \ (select_object_any0\<^sub>S\<^sub>e\<^sub>t f s_set)" shows "s_set \ []" apply(insert def_sel, case_tac s_set) apply(simp add: select_object_any0\<^sub>S\<^sub>e\<^sub>t_def UML_Sequence.OclANY_def select_object\<^sub>S\<^sub>e\<^sub>t_def select_object_def defined_def OclValid_def false_def true_def bot_fun_def bot_option_def split: if_split_asm) by(simp) lemma select_object_any_defined\<^sub>S\<^sub>e\<^sub>t: assumes def_sel: "\ \ \ (select_object_any\<^sub>S\<^sub>e\<^sub>t f s_set)" shows "s_set \ []" apply(insert def_sel, case_tac s_set) apply(simp add: select_object_any\<^sub>S\<^sub>e\<^sub>t_def UML_Sequence.OclANY_def select_object\<^sub>S\<^sub>e\<^sub>t_def select_object_def defined_def OclValid_def false_def true_def bot_fun_def bot_option_def OclInt0_def OclInt1_def StrongEq_def OclIf_def null_fun_def null_option_def split: if_split_asm) by(simp) lemma select_object_any_exec0\<^sub>S\<^sub>e\<^sub>q: assumes def_sel: "\ \ \ (select_object_any\<^sub>S\<^sub>e\<^sub>q f s_set)" shows "\ \ (select_object_any\<^sub>S\<^sub>e\<^sub>q f s_set \ f (hd s_set))" apply(insert def_sel[simplified foundation16], simp add: select_object_any\<^sub>S\<^sub>e\<^sub>q_def foundation22 UML_Sequence.OclANY_def split: if_split_asm) apply(case_tac "\\Rep_Sequence\<^sub>b\<^sub>a\<^sub>s\<^sub>e (select_object\<^sub>S\<^sub>e\<^sub>q f s_set \)\\", simp add: bot_option_def, simp) apply(simp add: select_object\<^sub>S\<^sub>e\<^sub>q_def select_object_def) apply(subst (asm) select_fold_exec\<^sub>S\<^sub>e\<^sub>q) apply(rule fold_val_elem\<^sub>S\<^sub>e\<^sub>q, simp add: foundation18' invalid_def) apply(simp) by(drule arg_cong[where f = hd], subst (asm) hd_map, simp add: select_object_any_defined\<^sub>S\<^sub>e\<^sub>q[OF def_sel], simp) lemma select_object_any_exec\<^sub>S\<^sub>e\<^sub>q: assumes def_sel: "\ \ \ (select_object_any\<^sub>S\<^sub>e\<^sub>q f s_set)" shows "\e. List.member s_set e \ (\ \ (select_object_any\<^sub>S\<^sub>e\<^sub>q f s_set \ f e))" apply(insert select_object_any_exec0\<^sub>S\<^sub>e\<^sub>q[OF def_sel]) apply(rule exI[where x = "hd s_set"], simp) apply(case_tac s_set, simp add: select_object_any_defined\<^sub>S\<^sub>e\<^sub>q[OF def_sel]) by (metis list.sel member_rec(1)) lemma (*select_object_any_exec\<^sub>S\<^sub>e\<^sub>t:*) assumes def_sel: "\ \ \ (select_object_any0\<^sub>S\<^sub>e\<^sub>t f s_set)" shows "\ e. List.member s_set e \ (\ \ (select_object_any0\<^sub>S\<^sub>e\<^sub>t f s_set \ f e))" proof - have list_all_map: "\P f l. list_all P (List.map f l) = list_all (P o f) l" by(induct_tac l, simp_all) fix z show ?thesis when "\\Rep_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e (select_object\<^sub>S\<^sub>e\<^sub>t f s_set \)\\ = z" apply(insert that def_sel[simplified foundation16], simp add: select_object_any0\<^sub>S\<^sub>e\<^sub>t_def foundation22 UML_Set.OclANY_def null_fun_def split: if_split_asm) apply(simp add: select_object\<^sub>S\<^sub>e\<^sub>t_def select_object_def) apply(subst (asm) select_fold_exec\<^sub>S\<^sub>e\<^sub>t) apply(rule fold_val_elem\<^sub>S\<^sub>e\<^sub>t, simp add: OclValid_def) apply(simp add: comp_def) apply(case_tac s_set, simp, simp add: false_def true_def, simp) proof - fix a l show "insert (f a \) ((\x. f x \) ` set l) = z \ \e. List.member (a # l) e \ (SOME y. y \ z) = f e \" apply(rule list.induct[where P = "\l. \z a. insert (f a \) ((\x. f x \) ` set l) = z \ (\e. List.member (a # l) e \ ((SOME y. y \ z) = f e \))", THEN spec, THEN spec, THEN mp], intro allI impI) proof - fix x xa show "insert (f xa \) ((\x. f x \) ` set []) = x \ \e. List.member [xa] e \ (SOME y. y \ x) = f e \" apply(rule exI[where x = xa], simp add: List.member_def) apply(subst some_equality[where a = "f xa \"]) apply (metis (mono_tags) insertI1) apply (metis (mono_tags) empty_iff insert_iff) by(simp) apply_end(intro allI impI, simp) fix x list xa xb show " \x. \e. List.member (x # list) e \ (SOME y. y = f x \ \ y \ (\x. f x \) ` set list) = f e \ \ insert (f xb \) (insert (f x \) ((\x. f x \) ` set list)) = xa \ \e. List.member (xb # x # list) e \ (SOME y. y \ xa) = f e \" apply(case_tac "x = xb", simp) apply(erule allE[where x = xb]) apply(erule exE) proof - fix e show "insert (f xb \) ((\x. f x \) ` set list) = xa \ x = xb \ List.member (xb # list) e \ (SOME y. y = f xb \ \ y \ (\x. f x \) ` set list) = f e \ \ \e. List.member (xb # xb # list) e \ (SOME y. y \ xa) = f e \" apply(rule exI[where x = e], auto) by (metis member_rec(1)) apply_end(case_tac "List.member list x") apply_end(erule allE[where x = xb]) apply_end(erule exE) fix e let ?P = "\y. y = f xb \ \ y \ (\x. f x \) ` set list" show "insert (f xb \) (insert (f x \) ((\x. f x \) ` set list)) = xa \ x \ xb \ List.member list x \ List.member (xb # list) e \ (SOME y. y = f xb \ \ y \ (\x. f x \) ` set list) = f e \ \ \e. List.member (xb # x # list) e \ (SOME y. y \ xa) = f e \" apply(rule exI[where x = e], auto) apply (metis member_rec(1)) apply(subgoal_tac "?P (f e \)") prefer 2 apply(case_tac "xb = e", simp) apply (metis (mono_tags) image_eqI in_set_member member_rec(1)) apply(rule someI2[where a = "f e \"]) apply(erule disjE, simp)+ apply(rule disjI2)+ apply(simp) oops lemma select_object_any_exec\<^sub>S\<^sub>e\<^sub>t: assumes def_sel: "\ \ \ (select_object_any\<^sub>S\<^sub>e\<^sub>t f s_set)" shows "\ e. List.member s_set e \ (\ \ (select_object_any\<^sub>S\<^sub>e\<^sub>t f s_set \ f e))" proof - have card_singl: "\A a. finite A \ card (insert a A) = 1 \ A \ {a}" by (auto, metis Suc_inject card_Suc_eq card_eq_0_iff insert_absorb insert_not_empty singleton_iff) have list_same: "\f s_set z' x. f ` set s_set = {z'} \ List.member s_set x \ f x = z'" by (metis (full_types) empty_iff imageI in_set_member insert_iff) fix z show ?thesis when "\\Rep_Set\<^sub>b\<^sub>a\<^sub>s\<^sub>e (select_object\<^sub>S\<^sub>e\<^sub>t f s_set \)\\ = z" apply(insert that def_sel[simplified foundation16], simp add: select_object_any\<^sub>S\<^sub>e\<^sub>t_def foundation22 Let_def null_fun_def bot_fun_def OclIf_def split: if_split_asm) apply(simp add: StrongEq_def OclInt1_def true_def UML_Set.OclSize_def bot_option_def UML_Set.OclANY_def null_fun_def split: if_split_asm) apply(subgoal_tac "\z'. z = {z'}") prefer 2 apply(rule finite.cases[where a = z], simp, simp, simp) apply(rule card_singl, simp, simp) apply(erule exE, clarsimp) apply(simp add: select_object\<^sub>S\<^sub>e\<^sub>t_def select_object_def) apply(subst (asm) select_fold_exec\<^sub>S\<^sub>e\<^sub>t) apply(rule fold_val_elem\<^sub>S\<^sub>e\<^sub>t, simp add: OclValid_def true_def) apply(simp add: comp_def) apply(case_tac s_set, simp) proof - fix z' a list show "(\x. f x \) ` set s_set = {z'} \ s_set = a # list \ \e. List.member s_set e \ z' = f e \" apply(drule list_same[where x1 = a]) apply (metis member_rec(1)) by (metis (opaque_lifting, mono_tags) ListMem_iff elem in_set_member) qed qed blast+ end