From 70a24eef965301039e7d608e81dd1807692402b3 Mon Sep 17 00:00:00 2001 From: "Achim D. Brucker" Date: Wed, 10 Aug 2016 11:04:45 +0100 Subject: [PATCH] Import of Featherweight OCL release afp-Featherweight_OCL-2014-01-16 (Isabelle 2013-2). --- OCL_core.thy | 1519 +++++++++ OCL_lib.thy | 3172 +++++++++++++++++++ OCL_main.thy | 57 + OCL_state.thy | 1054 ++++++ OCL_tools.thy | 46 + ROOT | 24 + config | 9 + document/conclusion.tex | 187 ++ document/figures/AbstractSimpleChair.mp | 83 + document/figures/AbstractSimpleChair.pdf | Bin 0 -> 26644 bytes document/figures/jedit.png | Bin 0 -> 48776 bytes document/figures/pdf.png | Bin 0 -> 41815 bytes document/figures/person.png | Bin 0 -> 22079 bytes document/figures/pre-post.pdf | Bin 0 -> 25851 bytes document/formalization.tex | 34 + document/hol-ocl-isar.sty | 996 ++++++ document/introduction.tex | 1490 +++++++++ document/lstisar.sty | 423 +++ document/prooftree.sty | 347 ++ document/root.bib | 1384 ++++++++ document/root.tex | 157 + examples/Employee_AnalysisModel_OCLPart.thy | 143 + examples/Employee_AnalysisModel_UMLPart.thy | 1341 ++++++++ examples/Employee_DesignModel_OCLPart.thy | 143 + examples/Employee_DesignModel_UMLPart.thy | 1273 ++++++++ 25 files changed, 13882 insertions(+) create mode 100644 OCL_core.thy create mode 100644 OCL_lib.thy create mode 100644 OCL_main.thy create mode 100644 OCL_state.thy create mode 100644 OCL_tools.thy create mode 100644 ROOT create mode 100644 config create mode 100644 document/conclusion.tex create mode 100644 document/figures/AbstractSimpleChair.mp create mode 100644 document/figures/AbstractSimpleChair.pdf create mode 100644 document/figures/jedit.png create mode 100644 document/figures/pdf.png create mode 100644 document/figures/person.png create mode 100644 document/figures/pre-post.pdf create mode 100644 document/formalization.tex create mode 100644 document/hol-ocl-isar.sty create mode 100644 document/introduction.tex create mode 100644 document/lstisar.sty create mode 100644 document/prooftree.sty create mode 100644 document/root.bib create mode 100644 document/root.tex create mode 100644 examples/Employee_AnalysisModel_OCLPart.thy create mode 100644 examples/Employee_AnalysisModel_UMLPart.thy create mode 100644 examples/Employee_DesignModel_OCLPart.thy create mode 100644 examples/Employee_DesignModel_UMLPart.thy diff --git a/OCL_core.thy b/OCL_core.thy new file mode 100644 index 0000000..e9e01d6 --- /dev/null +++ b/OCL_core.thy @@ -0,0 +1,1519 @@ +(***************************************************************************** + * Featherweight-OCL --- A Formal Semantics for UML-OCL Version OCL 2.4 + * for the OMG Standard. + * http://www.brucker.ch/projects/hol-testgen/ + * + * OCL_core.thy --- Core definitions. + * This file is part of HOL-TestGen. + * + * Copyright (c) 2012-2013 Université Paris-Sud, France + * 2013 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. + ******************************************************************************) + +header{* Formalization I: Core Definitions *} + +theory + OCL_core +imports + Main +begin + +section{* Preliminaries *} +subsection{* Notations for the Option Type *} + +text{* + First of all, we will use a more compact notation for the library + option type which occur all over in our definitions and which will make + the presentation more like a textbook: +*} +notation Some ("\(_)\") +notation None ("\") + +text{* + The following function (corresponding to @{term the} in the Isabelle/HOL library) + is defined as the inverse of the injection @{term Some}. +*} +fun drop :: "'\ option \ '\" ("\(_)\") +where drop_lift[simp]: "\\v\\ = v" + + +subsection{* Minimal Notions of State and State Transitions *} +text{* Next we will introduce the foundational concept of an object id (oid), +which is just some infinite set. *} + +text{* In order to assure executability of as much as possible formulas, we fixed the +type of object id's to just natural numbers.*} +type_synonym oid = nat + +text{* We refrained from the alternative: +\begin{isar}[mathescape] +$\text{\textbf{type-synonym}}$ $\mathit{oid = ind}$ +\end{isar} +which is slightly more abstract but non-executable. +*} + +text{* + States are just a partial map from oid's to elements of an object + universe @{text "'\"}, and state transitions pairs of states + \ldots +*} +record ('\)state = + heap :: "oid \ '\ " + assocs\<^sub>2 :: "oid \ (oid \ oid) list" (* binary associations *) + assocs\<^sub>3 :: "oid \ (oid \ oid \ oid) list" (* ternary associations *) + + +type_synonym ('\)st = "'\ state \ '\ state" + +subsection{* Prerequisite: An Abstract Interface for OCL Types *} + +text {* + To have the possibility to nest collection types, + such that we can give semantics to expressions like @{text "Set{Set{\},null}"}, + it is necessary to introduce a uniform interface for types having + the @{text "invalid"} (= bottom) element. The reason is that we impose + a data-invariant on raw-collection \inlineisar|types_code| which assures + that the @{text "invalid"} element is not allowed inside the collection; + all raw-collections of this form were identified with the @{text "invalid"} element + itself. The construction requires that the new collection type is + not comparable with the raw-types (consisting of nested option type constructions), + such that the data-invariant must be expressed in terms of the interface. + In a second step, our base-types will be shown to be instances of this interface. + *} + +text{* + This uniform interface consists in a type class requiring the existence + of a bot and a null element. The construction proceeds by + abstracting the null (defined by @{text "\ \ \"} on + @{text "'a option option"}) to a @{text null} element, which may + have an arbitrary semantic structure, and an undefinedness element @{text "\ "} + to an abstract undefinedness element @{text "bot"} (also written + @{text "\ "} whenever no confusion arises). As a consequence, it is necessary + to redefine the notions of invalid, defined, valuation etc. + on top of this interface. *} + +text{* + This interface consists in two abstract type classes @{text bot} + and @{text null} for the class of all types comprising a bot and a + distinct null element. *} + +class bot = + fixes bot :: "'a" + assumes nonEmpty : "\ x. x \ bot" + + +class null = bot + + fixes null :: "'a" + assumes null_is_valid : "null \ bot" + + +subsection{* Accommodation of Basic Types to the Abstract Interface *} + +text{* + In the following it is shown that the ``option-option'' type is + in fact in the @{text null} class and that function spaces over these + classes again ``live'' in these classes. This motivates the default construction + of the semantic domain for the basic types (\inlineocl{Boolean}, + \inlineocl{Integer}, \inlineocl{Real}, \ldots). +*} + +instantiation option :: (type)bot +begin + definition bot_option_def: "(bot::'a option) \ (None::'a option)" + instance proof show "\x\'a option. x \ bot" + by(rule_tac x="Some x" in exI, simp add:bot_option_def) + qed +end + + +instantiation option :: (bot)null +begin + definition null_option_def: "(null::'a\bot option) \ \ bot \" + instance proof show "(null::'a\bot option) \ bot" + by( simp add:null_option_def bot_option_def) + qed +end + + +instantiation "fun" :: (type,bot) bot +begin + definition bot_fun_def: "bot \ (\ x. bot)" + + instance proof show "\(x::'a \ 'b). x \ bot" + apply(rule_tac x="\ _. (SOME y. y \ bot)" in exI, auto) + apply(drule_tac x=x in fun_cong,auto simp:bot_fun_def) + apply(erule contrapos_pp, simp) + apply(rule some_eq_ex[THEN iffD2]) + apply(simp add: nonEmpty) + done + qed +end + + +instantiation "fun" :: (type,null) null +begin + definition null_fun_def: "(null::'a \ 'b::null) \ (\ x. null)" + + instance proof + show "(null::'a \ 'b::null) \ bot" + apply(auto simp: null_fun_def bot_fun_def) + apply(drule_tac x=x in fun_cong) + apply(erule contrapos_pp, simp add: null_is_valid) + done + qed +end + +text{* A trivial consequence of this adaption of the interface is that +abstract and concrete versions of null are the same on base types +(as could be expected). *} + +subsection{* The Semantic Space of OCL Types: Valuations *} + +text{* Valuations are now functions from a state pair (built upon +data universe @{typ "'\"}) to an arbitrary null-type (\ie, containing +at least a destinguished @{text "null"} and @{text "invalid"} element). *} + +type_synonym ('\,'\) val = "'\ st \ '\::null" + +text{* The definitions for the constants and operations based on valuations +will be geared towards a format that Isabelle can check to be a ``conservative'' +(\ie, logically safe) axiomatic definition. By introducing an explicit +interpretation function (which happens to be defined just as the identity +since we are using a shallow embedding of OCL into HOL), all these definitions +can be rewritten into the conventional semantic textbook format as follows: *} + +definition Sem :: "'a \ 'a" ("I\_\") +where "I\x\ \ x" + +text{* As a consequence of semantic domain definition, any OCL type will +have the two semantic constants @{text "invalid"} (for exceptional, aborted +computation) and @{text "null"}: + *} + +definition invalid :: "('\,'\::bot) val" +where "invalid \ \ \. bot" + +text{* This conservative Isabelle definition of the polymorphic constant +@{const invalid} is equivalent with the textbook definition: *} + +lemma textbook_invalid: "I\invalid\\ = bot" +by(simp add: invalid_def Sem_def) + + +text {* Note that the definition : +{\small +\begin{isar}[mathescape] +definition null :: "('$\mathfrak{A}$,'\::null) val" +where "null \ \ \. null" +\end{isar} +} is not necessary since we defined the entire function space over null types +again as null-types; the crucial definition is @{thm "null_fun_def"}. +Thus, the polymorphic constant @{const null} is simply the result of +a general type class construction. Nevertheless, we can derive the +semantic textbook definition for the OCL null constant based on the +abstract null: +*} + +lemma textbook_null_fun: "I\null::('\,'\::null) val\ \ = (null::'\::null)" +by(simp add: null_fun_def Sem_def) + + +section{* Definition of the Boolean Type *} + +text{* The semantic domain of the (basic) boolean type is now defined as the Standard: +the space of valuation to @{typ "bool option option"}:*} + +type_synonym ('\)Boolean = "('\,bool option option) val" + +subsection{* Basic Constants *} + +lemma bot_Boolean_def : "(bot::('\)Boolean) = (\ \. \)" +by(simp add: bot_fun_def bot_option_def) + +lemma null_Boolean_def : "(null::('\)Boolean) = (\ \. \\\)" +by(simp add: null_fun_def null_option_def bot_option_def) + +definition true :: "('\)Boolean" +where "true \ \ \. \\True\\" + + +definition false :: "('\)Boolean" +where "false \ \ \. \\False\\" + +lemma bool_split: "X \ = invalid \ \ X \ = null \ \ + X \ = true \ \ X \ = false \" +apply(simp add: invalid_def null_def true_def false_def) +apply(case_tac "X \",simp_all add: null_fun_def null_option_def bot_option_def) +apply(case_tac "a",simp) +apply(case_tac "aa",simp) +apply auto +done + + + +lemma [simp]: "false (a, b) = \\False\\" +by(simp add:false_def) + +lemma [simp]: "true (a, b) = \\True\\" +by(simp add:true_def) + +lemma textbook_true: "I\true\ \ = \\True\\" +by(simp add: Sem_def true_def) + +lemma textbook_false: "I\false\ \ = \\False\\" +by(simp add: Sem_def false_def) + +text {* +\begin{table}[htbp] + \centering + \begin{tabu}{lX[,c,]} + \toprule + Name & Theorem \\ + \midrule + @{thm [source] textbook_invalid} & @{thm [display=false] textbook_invalid} \\ + @{thm [source] textbook_null_fun} & @{thm [display=false] textbook_null_fun} \\ + @{thm [source] textbook_true} & @{thm [display=false] textbook_true} \\ + @{thm [source] textbook_false} & @{thm [display=false] textbook_false} \\ + \bottomrule + \end{tabu} + \caption{Basic semantic constant definitions of the logic (except @{term null})} + \label{tab:sem_basic_constants} +\end{table} +*} + +subsection{* Validity and Definedness *} + +text{* However, this has also the consequence that core concepts like definedness, +validness and even cp have to be redefined on this type class:*} + +definition valid :: "('\,'a::null)val \ ('\)Boolean" ("\ _" [100]100) +where "\ X \ \ \ . if X \ = bot \ then false \ else true \" + +lemma valid1[simp]: "\ invalid = false" + by(rule ext,simp add: valid_def bot_fun_def bot_option_def + invalid_def true_def false_def) + +lemma valid2[simp]: "\ null = true" + by(rule ext,simp add: valid_def bot_fun_def bot_option_def null_is_valid + null_fun_def invalid_def true_def false_def) + +lemma valid3[simp]: "\ true = true" + by(rule ext,simp add: valid_def bot_fun_def bot_option_def null_is_valid + null_fun_def invalid_def true_def false_def) + +lemma valid4[simp]: "\ false = true" + by(rule ext,simp add: valid_def bot_fun_def bot_option_def null_is_valid + null_fun_def invalid_def true_def false_def) + + +lemma cp_valid: "(\ X) \ = (\ (\ _. X \)) \" +by(simp add: valid_def) + + + +definition defined :: "('\,'a::null)val \ ('\)Boolean" ("\ _" [100]100) +where "\ X \ \ \ . if X \ = bot \ \ X \ = null \ then false \ else true \" + +text{* The generalized definitions of invalid and definedness have the same +properties as the old ones : *} +lemma defined1[simp]: "\ invalid = false" + by(rule ext,simp add: defined_def bot_fun_def bot_option_def + null_def invalid_def true_def false_def) + +lemma defined2[simp]: "\ null = false" + by(rule ext,simp add: defined_def bot_fun_def bot_option_def + null_def null_option_def null_fun_def invalid_def true_def false_def) + + +lemma defined3[simp]: "\ true = true" + by(rule ext,simp add: defined_def bot_fun_def bot_option_def null_is_valid null_option_def + null_fun_def invalid_def true_def false_def) + +lemma defined4[simp]: "\ false = true" + by(rule ext,simp add: defined_def bot_fun_def bot_option_def null_is_valid null_option_def + null_fun_def invalid_def true_def false_def) + + +lemma defined5[simp]: "\ \ X = true" + by(rule ext, + auto simp: defined_def true_def false_def + bot_fun_def bot_option_def null_option_def null_fun_def) + +lemma defined6[simp]: "\ \ X = true" + by(rule ext, + auto simp: valid_def defined_def true_def false_def + bot_fun_def bot_option_def null_option_def null_fun_def) + +lemma valid5[simp]: "\ \ X = true" + by(rule ext, + auto simp: valid_def true_def false_def + bot_fun_def bot_option_def null_option_def null_fun_def) + +lemma valid6[simp]: "\ \ X = true" + by(rule ext, + auto simp: valid_def defined_def true_def false_def + bot_fun_def bot_option_def null_option_def null_fun_def) + + +lemma cp_defined:"(\ X)\ = (\ (\ _. X \)) \" +by(simp add: defined_def) + +text{* The definitions above for the constants @{const defined} and @{const valid} +can be rewritten into the conventional semantic "textbook" format as follows: *} + +lemma textbook_defined: "I\\(X)\ \ = (if I\X\ \ = I\bot\ \ \ I\X\ \ = I\null\ \ + then I\false\ \ + else I\true\ \)" +by(simp add: Sem_def defined_def) + +lemma textbook_valid: "I\\(X)\ \ = (if I\X\ \ = I\bot\ \ + then I\false\ \ + else I\true\ \)" +by(simp add: Sem_def valid_def) + + +text {* +\autoref{tab:sem_definedness} and \autoref{tab:alglaws_definedness} +summarize the results of this section. +\begin{table}[htbp] + \centering + \begin{tabu}{lX[,c,]} + \toprule + Name & Theorem \\ + \midrule + @{thm [source] textbook_defined} & @{thm [show_question_marks=false,display=false,margin=45] textbook_defined} \\ + @{thm [source] textbook_valid} & @{thm [show_question_marks=false,display=false,margin=45] textbook_valid} \\ + \bottomrule + \end{tabu} + \caption{Basic predicate definitions of the logic.} + \label{tab:sem_definedness} +\end{table} +\begin{table}[htbp] + \centering + \begin{tabu}{lX[,c,]} + \toprule + Name & Theorem \\ + \midrule + @{thm [source] defined1} & @{thm defined1} \\ + @{thm [source] defined2} & @{thm [display=false,margin=35] defined2} \\ + @{thm [source] defined3} & @{thm [display=false,margin=35] defined3} \\ + @{thm [source] defined4} & @{thm [display=false,margin=35] defined4} \\ + @{thm [source] defined5} & @{thm [display=false,margin=35] defined5} \\ + @{thm [source] defined6} & @{thm [display=false,margin=35] defined6} \\ + \bottomrule + \end{tabu} + \caption{Laws of the basic predicates of the logic.} + \label{tab:alglaws_definedness} +\end{table} +*} + +section{* The Equalities of OCL *} +text{* + The OCL contains a particular version of equality, written in + Standard documents \inlineocl+_ = _+ and \inlineocl+_ <> _+ for its + negation, which is referred as \emph{weak referential equality} + hereafter and for which we use the symbol \inlineisar+_ \ _+ + throughout the formal part of this document. Its semantics is + motivated by the desire of fast execution, and similarity to + languages like Java and C, but does not satisfy the needs of logical + reasoning over OCL expressions and specifications. We therefore + introduce a second equality, referred as \emph{strong equality} or + \emph{logical equality} and written \inlineisar+_ \ _+ + which is not present in the current standard but was discussed in + prior texts on OCL like the Amsterdam + Manifesto~\cite{cook.ea::amsterdam:2002} and was identified as + desirable extension of OCL in the Aachen + Meeting~\cite{brucker.ea:summary-aachen:2013} in the future 2.5 OCL + Standard. The purpose of strong equality is to define and reason + over OCL. It is therefore a natural task in Featherweight OCL to + formally investigate the somewhat quite complex relationship between + these two. *} text{* Strong equality has two motivations: a + pragmatic one and a fundamental one. + \begin{enumerate} + \item The pragmatic reason is fairly simple: users of object-oriented languages want + something like a ``shallow object value equality''. + You will want to say + \inlineisar+ a.boss \ b.boss@pre + + instead of +\begin{isar} + a.boss \ b.boss@pre and (* just the pointers are equal! *) + a.boss.name \ b.boss@pre.name@pre and + a.boss.age \ b.boss@pre.age@pre +\end{isar} + Breaking a shallow-object equality down to referential equality + of attributes is cumbersome, error-prone, and makes + specifications difficult to extend (add for example an attribute + sex to your class, and check in your OCL specification + everywhere that you did it right with your simulation of strong + equality). Therefore, languages like Java offer facilities + to handle two different equalities, and it is problematic even + in an execution oriented specification language to ignore + shallow object equality because it is so common in the code. + \item The fundamental reason goes as follows: whatever you do to + reason consistently over a language, you need the concept of + equality: you need to know what expressions can be replaced by + others because they \emph{mean the same thing.} People call + this also ``Leibniz Equality'' because this philosopher brought + this principle first explicitly to paper and shed some light + over it. It is the theoretic foundation of what you do in an + optimizing compiler: you replace expressions by \emph{equal} + ones, which you hope are easier to evaluate. In a typed + language, strong equality exists uniformly over all types, it is + ``polymorphic'' $\_ = \_ :: \alpha * \alpha \rightarrow + bool$---this is the way that equality is defined in HOL itself. + We can express Leibniz principle as one logical rule of + surprising simplicity and beauty: + \begin{gather} + s = t \Longrightarrow P(s) = P(t) + \end{gather} + ``Whenever we know, that $s$ is equal to $t$, we can replace the + sub-expression $s$ in a term $P$ by $t$ and we have that the + replacement is equal to the original.'' +\end{enumerate} +*} +text{* + While weak referential equality is defined to be strict in the OCL + standard, we will define strong equality as non-strict. It is quite + nasty (but not impossible) to define the logical equality in a + strict way (the substitutivity rule above would look more complex), + however, whenever references were used, strong equality is needed + since references refer to particular states (pre or post), and that + they mean the same thing can therefore not be taken for granted. +*} + +subsection{* Definition *} +text{* + The strict equality on basic types (actually on all types) must be + exceptionally defined on @{term "null"}---otherwise the entire + concept of null in the language does not make much sense. This is an + important exception from the general rule that null + arguments---especially if passed as ``self''-argument---lead to + invalid results. +*} + + +text{* + We define strong equality extremely generic, even for types that + contain a @{text "null"} or @{text "\"} element. Strong + equality is simply polymorphic in Featherweight OCL, \ie, is + defined identical for all types in OCL and HOL. +*} +definition StrongEq::"['\ st \ '\,'\ st \ '\] \ ('\)Boolean" (infixl "\" 30) +where "X \ Y \ \ \. \\X \ = Y \ \\" + +text{* + From this follow already elementary properties like: +*} +lemma [simp,code_unfold]: "(true \ false) = false" +by(rule ext, auto simp: StrongEq_def) + +lemma [simp,code_unfold]: "(false \ true) = false" +by(rule ext, auto simp: StrongEq_def) + + +text{* + In contrast, referential equality behaves differently for all + types---on value types, it is basically strong equality for defined + values, but on object types it will compare references---we + introduce it as an \emph{overloaded} concept and will handle it for + each type instance individually. +*} +consts StrictRefEq :: "[('\,'a)val,('\,'a)val] \ ('\)Boolean" (infixl "\" 30) + + +text{* + Here is a first instance of a definition of weak equality---for + the special case of the type @{typ "('\)Boolean"}, it is just + the strict extension of the logical + equality: +*} +defs StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n[code_unfold] : + "(x::('\)Boolean) \ y \ \ \. if (\ x) \ = true \ \ (\ y) \ = true \ + then (x \ y)\ + else invalid \" + +text{* which implies elementary properties like: *} +lemma [simp,code_unfold] : "(true \ false) = false" +by(simp add:StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n) +lemma [simp,code_unfold] : "(false \ true) = false" +by(simp add:StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n) + +lemma [simp,code_unfold] : "(invalid \ false) = invalid" +by(simp add:StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n false_def true_def) +lemma [simp,code_unfold] : "(invalid \ true) = invalid" +by(simp add:StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n false_def true_def) + +lemma [simp,code_unfold] : "(false \ invalid) = invalid" +by(simp add:StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n false_def true_def) +lemma [simp,code_unfold] : "(true \ invalid) = invalid" +by(simp add:StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n false_def true_def) + +lemma [simp,code_unfold] : "((invalid::('\)Boolean) \ invalid) = invalid" +by(simp add:StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n false_def true_def) +text{* Thus, the weak equality is \emph{not} reflexive. *} + +lemma null_non_false [simp,code_unfold]:"(null \ false) = false" + apply(rule ext, simp add: StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n StrongEq_def false_def) +by (metis OCL_core.drop.simps cp_valid false_def is_none_code(2) is_none_def valid4 + bot_option_def null_fun_def null_option_def) + +lemma null_non_true [simp,code_unfold]:"(null \ true) = false" + apply(rule ext, simp add: StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n StrongEq_def false_def) +by(simp add: true_def bot_option_def null_fun_def null_option_def) + +lemma false_non_null [simp,code_unfold]:"(false \ null) = false" + apply(rule ext, simp add: StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n StrongEq_def false_def) +by (metis OCL_core.drop.simps cp_valid false_def is_none_code(2) is_none_def valid4 + bot_option_def null_fun_def null_option_def ) + +lemma true_non_null [simp,code_unfold]:"(true \ null) = false" + apply(rule ext, simp add: StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n StrongEq_def false_def) +by(simp add: true_def bot_option_def null_fun_def null_option_def) + +subsection{* Fundamental Predicates on Strong Equality *} + +text{* Equality reasoning in OCL is not humpty dumpty. While strong equality +is clearly an equivalence: *} +lemma StrongEq_refl [simp]: "(X \ X) = true" +by(rule ext, simp add: null_def invalid_def true_def false_def StrongEq_def) + +lemma StrongEq_sym: "(X \ Y) = (Y \ X)" +by(rule ext, simp add: eq_sym_conv invalid_def true_def false_def StrongEq_def) + +lemma StrongEq_trans_strong [simp]: + assumes A: "(X \ Y) = true" + and B: "(Y \ Z) = true" + shows "(X \ Z) = true" + apply(insert A B) apply(rule ext) + apply(simp add: null_def invalid_def true_def false_def StrongEq_def) + apply(drule_tac x=x in fun_cong)+ + by auto + +text{* + it is only in a limited sense a congruence, at least from the + point of view of this semantic theory. The point is that it is + only a congruence on OCL expressions, not arbitrary HOL + expressions (with which we can mix Featherweight OCL expressions). A + semantic---not syntactic---characterization of OCL expressions is + that they are \emph{context-passing} or \emph{context-invariant}, + \ie, the context of an entire OCL expression, \ie the pre and + post state it referes to, is passed constantly and unmodified to + the sub-expressions, \ie, all sub-expressions inside an OCL + expression refer to the same context. Expressed formally, this + boils down to: +*} +lemma StrongEq_subst : + assumes cp: "\X. P(X)\ = P(\ _. X \)\" + and eq: "(X \ Y)\ = true \" + shows "(P X \ P Y)\ = true \" + apply(insert cp eq) + apply(simp add: null_def invalid_def true_def false_def StrongEq_def) + apply(subst cp[of X]) + apply(subst cp[of Y]) + by simp + +lemma defined7[simp]: "\ (X \ Y) = true" + by(rule ext, + auto simp: defined_def true_def false_def StrongEq_def + bot_fun_def bot_option_def null_option_def null_fun_def) + +lemma valid7[simp]: "\ (X \ Y) = true" + by(rule ext, + auto simp: valid_def true_def false_def StrongEq_def + bot_fun_def bot_option_def null_option_def null_fun_def) + +lemma cp_StrongEq: "(X \ Y) \ = ((\ _. X \) \ (\ _. Y \)) \" +by(simp add: StrongEq_def) + +section{* Logical Connectives and their Universal Properties *} +text{* + It is a design goal to give OCL a semantics that is as closely as + possible to a ``logical system'' in a known sense; a specification + logic where the logical connectives can not be understood other that + having the truth-table aside when reading fails its purpose in our + view. + + Practically, this means that we want to give a definition to the + core operations to be as close as possible to the lattice laws; this + makes also powerful symbolic normalization of OCL specifications + possible as a pre-requisite for automated theorem provers. For + example, it is still possible to compute without any definedness + and validity reasoning the DNF of an OCL specification; be it for + test-case generations or for a smooth transition to a two-valued + representation of the specification amenable to fast standard + SMT-solvers, for example. + + Thus, our representation of the OCL is merely a 4-valued + Kleene-Logics with @{term "invalid"} as least, @{term "null"} as + middle and @{term "true"} resp. @{term "false"} as unrelated + top-elements. +*} + + +definition OclNot :: "('\)Boolean \ ('\)Boolean" ("not") +where "not X \ \ \ . case X \ of + \ \ \ + | \ \ \ \ \ \ \ + | \\ x \\ \ \\ \ x \\" + +text{* with {term "not"} we can express the notation:*} + +syntax + "notequal" :: "('\)Boolean \ ('\)Boolean \ ('\)Boolean" (infix "<>" 40) +translations + "a <> b" == "CONST OclNot( a \ b)" + + + +lemma cp_OclNot: "(not X)\ = (not (\ _. X \)) \" +by(simp add: OclNot_def) + +lemma OclNot1[simp]: "not invalid = invalid" + by(rule ext,simp add: OclNot_def null_def invalid_def true_def false_def bot_option_def) + +lemma OclNot2[simp]: "not null = null" + by(rule ext,simp add: OclNot_def null_def invalid_def true_def false_def + bot_option_def null_fun_def null_option_def ) + +lemma OclNot3[simp]: "not true = false" + by(rule ext,simp add: OclNot_def null_def invalid_def true_def false_def) + +lemma OclNot4[simp]: "not false = true" + by(rule ext,simp add: OclNot_def null_def invalid_def true_def false_def) + + +lemma OclNot_not[simp]: "not (not X) = X" + apply(rule ext,simp add: OclNot_def null_def invalid_def true_def false_def) + apply(case_tac "X x", simp_all) + apply(case_tac "a", simp_all) + done + +lemma OclNot_inject: "\ x y. not x = not y \ x = y" + by(subst OclNot_not[THEN sym], simp) + +definition OclAnd :: "[('\)Boolean, ('\)Boolean] \ ('\)Boolean" (infixl "and" 30) +where "X and Y \ (\ \ . case X \ of + \\False\\ \ \\False\\ + | \ \ (case Y \ of + \\False\\ \ \\False\\ + | _ \ \) + | \\\ \ (case Y \ of + \\False\\ \ \\False\\ + | \ \ \ + | _ \ \\\) + | \\True\\ \ Y \)" + + +text{* + Note that @{term "not"} is \emph{not} defined as a strict function; + proximity to lattice laws implies that we \emph{need} a definition + of @{term "not"} that satisfies @{text "not(not(x))=x"}. +*} + +text{* + In textbook notation, the logical core constructs @{const + "OclNot"} and @{const "OclAnd"} were represented as follows: +*} +lemma textbook_OclNot: + "I\not(X)\ \ = (case I\X\ \ of \ \ \ + | \ \ \ \ \ \ \ + | \\ x \\ \ \\ \ x \\)" +by(simp add: Sem_def OclNot_def) + +lemma textbook_OclAnd: + "I\X and Y\ \ = (case I\X\ \ of + \ \ (case I\Y\ \ of + \ \ \ + | \\\ \ \ + | \\True\\ \ \ + | \\False\\ \ \\False\\) + | \ \ \ \ (case I\Y\ \ of + \ \ \ + | \\\ \ \\\ + | \\True\\ \ \\\ + | \\False\\ \ \\False\\) + | \\True\\ \ (case I\Y\ \ of + \ \ \ + | \\\ \ \\\ + | \\y\\ \ \\y\\) + | \\False\\ \ \\ False \\)" +by(simp add: OclAnd_def Sem_def split: option.split bool.split) + +definition OclOr :: "[('\)Boolean, ('\)Boolean] \ ('\)Boolean" (infixl "or" 25) +where "X or Y \ not(not X and not Y)" + +definition OclImplies :: "[('\)Boolean, ('\)Boolean] \ ('\)Boolean" (infixl "implies" 25) +where "X implies Y \ not X or Y" + +lemma cp_OclAnd:"(X and Y) \ = ((\ _. X \) and (\ _. Y \)) \" +by(simp add: OclAnd_def) + +lemma cp_OclOr:"((X::('\)Boolean) or Y) \ = ((\ _. X \) or (\ _. Y \)) \" +apply(simp add: OclOr_def) +apply(subst cp_OclNot[of "not (\_. X \) and not (\_. Y \)"]) +apply(subst cp_OclAnd[of "not (\_. X \)" "not (\_. Y \)"]) +by(simp add: cp_OclNot[symmetric] cp_OclAnd[symmetric] ) + + +lemma cp_OclImplies:"(X implies Y) \ = ((\ _. X \) implies (\ _. Y \)) \" +apply(simp add: OclImplies_def) +apply(subst cp_OclOr[of "not (\_. X \)" "(\_. Y \)"]) +by(simp add: cp_OclNot[symmetric] cp_OclOr[symmetric] ) + +lemma OclAnd1[simp]: "(invalid and true) = invalid" + by(rule ext,simp add: OclAnd_def null_def invalid_def true_def false_def bot_option_def) +lemma OclAnd2[simp]: "(invalid and false) = false" + by(rule ext,simp add: OclAnd_def null_def invalid_def true_def false_def bot_option_def) +lemma OclAnd3[simp]: "(invalid and null) = invalid" + by(rule ext,simp add: OclAnd_def null_def invalid_def true_def false_def bot_option_def + null_fun_def null_option_def) +lemma OclAnd4[simp]: "(invalid and invalid) = invalid" + by(rule ext,simp add: OclAnd_def null_def invalid_def true_def false_def bot_option_def) + +lemma OclAnd5[simp]: "(null and true) = null" + by(rule ext,simp add: OclAnd_def null_def invalid_def true_def false_def bot_option_def + null_fun_def null_option_def) +lemma OclAnd6[simp]: "(null and false) = false" + by(rule ext,simp add: OclAnd_def null_def invalid_def true_def false_def bot_option_def + null_fun_def null_option_def) +lemma OclAnd7[simp]: "(null and null) = null" + by(rule ext,simp add: OclAnd_def null_def invalid_def true_def false_def bot_option_def + null_fun_def null_option_def) +lemma OclAnd8[simp]: "(null and invalid) = invalid" + by(rule ext,simp add: OclAnd_def null_def invalid_def true_def false_def bot_option_def + null_fun_def null_option_def) + +lemma OclAnd9[simp]: "(false and true) = false" + by(rule ext,simp add: OclAnd_def null_def invalid_def true_def false_def) +lemma OclAnd10[simp]: "(false and false) = false" + by(rule ext,simp add: OclAnd_def null_def invalid_def true_def false_def) +lemma OclAnd11[simp]: "(false and null) = false" + by(rule ext,simp add: OclAnd_def null_def invalid_def true_def false_def) +lemma OclAnd12[simp]: "(false and invalid) = false" + by(rule ext,simp add: OclAnd_def null_def invalid_def true_def false_def) + +lemma OclAnd13[simp]: "(true and true) = true" + by(rule ext,simp add: OclAnd_def null_def invalid_def true_def false_def) +lemma OclAnd14[simp]: "(true and false) = false" + by(rule ext,simp add: OclAnd_def null_def invalid_def true_def false_def) +lemma OclAnd15[simp]: "(true and null) = null" + by(rule ext,simp add: OclAnd_def null_def invalid_def true_def false_def bot_option_def + null_fun_def null_option_def) +lemma OclAnd16[simp]: "(true and invalid) = invalid" + by(rule ext,simp add: OclAnd_def null_def invalid_def true_def false_def bot_option_def + null_fun_def null_option_def) + +lemma OclAnd_idem[simp]: "(X and X) = X" + apply(rule ext,simp add: OclAnd_def null_def invalid_def true_def false_def) + apply(case_tac "X x", simp_all) + apply(case_tac "a", simp_all) + apply(case_tac "aa", simp_all) + done + +lemma OclAnd_commute: "(X and Y) = (Y and X)" + by(rule ext,auto simp:true_def false_def OclAnd_def invalid_def + split: option.split option.split_asm + bool.split bool.split_asm) + + +lemma OclAnd_false1[simp]: "(false and X) = false" + apply(rule ext, simp add: OclAnd_def) + apply(auto simp:true_def false_def invalid_def + split: option.split option.split_asm) + done + +lemma OclAnd_false2[simp]: "(X and false) = false" + by(simp add: OclAnd_commute) + + +lemma OclAnd_true1[simp]: "(true and X) = X" + apply(rule ext, simp add: OclAnd_def) + apply(auto simp:true_def false_def invalid_def + split: option.split option.split_asm) + done + +lemma OclAnd_true2[simp]: "(X and true) = X" + by(simp add: OclAnd_commute) + +lemma OclAnd_bot1[simp]: "\\. X \ \ false \ \ (bot and X) \ = bot \" + apply(simp add: OclAnd_def) + apply(auto simp:true_def false_def bot_fun_def bot_option_def + split: option.split option.split_asm) +done + +lemma OclAnd_bot2[simp]: "\\. X \ \ false \ \ (X and bot) \ = bot \" + by(simp add: OclAnd_commute) + +lemma OclAnd_null1[simp]: "\\. X \ \ false \ \ X \ \ bot \ \ (null and X) \ = null \" + apply(simp add: OclAnd_def) + apply(auto simp:true_def false_def bot_fun_def bot_option_def null_fun_def null_option_def + split: option.split option.split_asm) +done + +lemma OclAnd_null2[simp]: "\\. X \ \ false \ \ X \ \ bot \ \ (X and null) \ = null \" + by(simp add: OclAnd_commute) + +lemma OclAnd_assoc: "(X and (Y and Z)) = (X and Y and Z)" + apply(rule ext, simp add: OclAnd_def) + apply(auto simp:true_def false_def null_def invalid_def + split: option.split option.split_asm + bool.split bool.split_asm) +done + + +lemma OclOr1[simp]: "(invalid or true) = true" +by(rule ext, simp add: OclOr_def OclNot_def OclAnd_def null_def invalid_def true_def false_def + bot_option_def) +lemma OclOr2[simp]: "(invalid or false) = invalid" +by(rule ext, simp add: OclOr_def OclNot_def OclAnd_def null_def invalid_def true_def false_def + bot_option_def) +lemma OclOr3[simp]: "(invalid or null) = invalid" +by(rule ext, simp add: OclOr_def OclNot_def OclAnd_def null_def invalid_def true_def false_def + bot_option_def null_fun_def null_option_def) +lemma OclOr4[simp]: "(invalid or invalid) = invalid" +by(rule ext, simp add: OclOr_def OclNot_def OclAnd_def null_def invalid_def true_def false_def + bot_option_def) + +lemma OclOr5[simp]: "(null or true) = true" +by(rule ext, simp add: OclOr_def OclNot_def OclAnd_def null_def invalid_def true_def false_def + bot_option_def null_fun_def null_option_def) +lemma OclOr6[simp]: "(null or false) = null" +by(rule ext, simp add: OclOr_def OclNot_def OclAnd_def null_def invalid_def true_def false_def + bot_option_def null_fun_def null_option_def) +lemma OclOr7[simp]: "(null or null) = null" +by(rule ext, simp add: OclOr_def OclNot_def OclAnd_def null_def invalid_def true_def false_def + bot_option_def null_fun_def null_option_def) +lemma OclOr8[simp]: "(null or invalid) = invalid" +by(rule ext, simp add: OclOr_def OclNot_def OclAnd_def null_def invalid_def true_def false_def + bot_option_def null_fun_def null_option_def) + +lemma OclOr_idem[simp]: "(X or X) = X" + by(simp add: OclOr_def) + +lemma OclOr_commute: "(X or Y) = (Y or X)" + by(simp add: OclOr_def OclAnd_commute) + +lemma OclOr_false1[simp]: "(false or Y) = Y" + by(simp add: OclOr_def) + +lemma OclOr_false2[simp]: "(Y or false) = Y" + by(simp add: OclOr_def) + +lemma OclOr_true1[simp]: "(true or Y) = true" + by(simp add: OclOr_def) + +lemma OclOr_true2: "(Y or true) = true" + by(simp add: OclOr_def) + +lemma OclOr_bot1[simp]: "\\. X \ \ true \ \ (bot or X) \ = bot \" + apply(simp add: OclOr_def OclAnd_def OclNot_def) + apply(auto simp:true_def false_def bot_fun_def bot_option_def + split: option.split option.split_asm) +done + +lemma OclOr_bot2[simp]: "\\. X \ \ true \ \ (X or bot) \ = bot \" + by(simp add: OclOr_commute) + +lemma OclOr_null1[simp]: "\\. X \ \ true \ \ X \ \ bot \ \ (null or X) \ = null \" + apply(simp add: OclOr_def OclAnd_def OclNot_def) + apply(auto simp:true_def false_def bot_fun_def bot_option_def null_fun_def null_option_def + split: option.split option.split_asm) + apply (metis (full_types) bool.simps(3) bot_option_def null_is_valid null_option_def) +by (metis (full_types) bool.simps(3) option.distinct(1) the.simps) + +lemma OclOr_null2[simp]: "\\. X \ \ true \ \ X \ \ bot \ \ (X or null) \ = null \" + by(simp add: OclOr_commute) + +lemma OclOr_assoc: "(X or (Y or Z)) = (X or Y or Z)" + by(simp add: OclOr_def OclAnd_assoc) + +lemma OclImplies_true: "(X implies true) = true" + by (simp add: OclImplies_def OclOr_true2) + +lemma deMorgan1: "not(X and Y) = ((not X) or (not Y))" + by(simp add: OclOr_def) + +lemma deMorgan2: "not(X or Y) = ((not X) and (not Y))" + by(simp add: OclOr_def) + + +section{* A Standard Logical Calculus for OCL *} +definition OclValid :: "[('\)st, ('\)Boolean] \ bool" ("(1(_)/ \ (_))" 50) +where "\ \ P \ ((P \) = true \)" + +value "\ \ true <> false" +value "\ \ false <> true" + +subsection{* Global vs. Local Judgements*} +lemma transform1: "P = true \ \ \ P" +by(simp add: OclValid_def) + + +lemma transform1_rev: "\ \. \ \ P \ P = true" +by(rule ext, auto simp: OclValid_def true_def) + +lemma transform2: "(P = Q) \ ((\ \ P) = (\ \ Q))" +by(auto simp: OclValid_def) + +lemma transform2_rev: "\ \. (\ \ \ P) \ (\ \ \ Q) \ (\ \ P) = (\ \ Q) \ P = Q" +apply(rule ext,auto simp: OclValid_def true_def defined_def) +apply(erule_tac x=a in allE) +apply(erule_tac x=b in allE) +apply(auto simp: false_def true_def defined_def bot_Boolean_def null_Boolean_def + split: option.split_asm HOL.split_if_asm) +done +(* Something stronger is possible here (consider P null, Q invalid), + but this thingi should do for our purpose *) + +text{* However, certain properties (like transitivity) can not + be \emph{transformed} from the global level to the local one, + they have to be re-proven on the local level. *} + +lemma (*transform3:*) +assumes H : "P = true \ Q = true" +shows "\ \ P \ \ \ Q" +apply(simp add: OclValid_def) +apply(rule H[THEN fun_cong]) +apply(rule ext) +oops + +subsection{* Local Validity and Meta-logic*} +text{* \label{sec:localVal} *} + +lemma foundation1[simp]: "\ \ true" +by(auto simp: OclValid_def) + +lemma foundation2[simp]: "\(\ \ false)" +by(auto simp: OclValid_def true_def false_def) + +lemma foundation3[simp]: "\(\ \ invalid)" +by(auto simp: OclValid_def true_def false_def invalid_def bot_option_def) + +lemma foundation4[simp]: "\(\ \ null)" +by(auto simp: OclValid_def true_def false_def null_def null_fun_def null_option_def bot_option_def) + +lemma bool_split_local[simp]: +"(\ \ (x \ invalid)) \ (\ \ (x \ null)) \ (\ \ (x \ true)) \ (\ \ (x \ false))" +apply(insert bool_split[of x \], auto) +apply(simp_all add: OclValid_def StrongEq_def true_def null_def invalid_def) +done + +lemma def_split_local: +"(\ \ \ x) = ((\(\ \ (x \ invalid))) \ (\ (\ \ (x \ null))))" +by(simp add:defined_def true_def false_def invalid_def null_def + StrongEq_def OclValid_def bot_fun_def null_fun_def) + +lemma foundation5: +"\ \ (P and Q) \ (\ \ P) \ (\ \ Q)" +by(simp add: OclAnd_def OclValid_def true_def false_def defined_def + split: option.split option.split_asm bool.split bool.split_asm) + +lemma foundation6: +"\ \ P \ \ \ \ P" +by(simp add: OclNot_def OclValid_def true_def false_def defined_def + null_option_def null_fun_def bot_option_def bot_fun_def + split: option.split option.split_asm) + + +lemma foundation7[simp]: +"(\ \ not (\ x)) = (\ (\ \ \ x))" +by(simp add: OclNot_def OclValid_def true_def false_def defined_def + split: option.split option.split_asm) + +lemma foundation7'[simp]: +"(\ \ not (\ x)) = (\ (\ \ \ x))" +by(simp add: OclNot_def OclValid_def true_def false_def valid_def + split: option.split option.split_asm) + + +text{* + Key theorem for the $\delta$-closure: either an expression is + defined, or it can be replaced (substituted via @{text "StrongEq_L_subst2"}; + see below) by @{text invalid} or @{text null}. Strictness-reduction rules will + usually reduce these substituted terms drastically. +*} +lemma foundation8: +"(\ \ \ x) \ (\ \ (x \ invalid)) \ (\ \ (x \ null))" +proof - + have 1 : "(\ \ \ x) \ (\(\ \ \ x))" by auto + have 2 : "(\(\ \ \ x)) = ((\ \ (x \ invalid)) \ (\ \ (x \ null)))" + by(simp only: def_split_local, simp) + show ?thesis by(insert 1, simp add:2) +qed + +lemma foundation9: +"\ \ \ x \ (\ \ not x) = (\ (\ \ x))" +apply(simp add: def_split_local ) +by(auto simp: OclNot_def null_fun_def null_option_def bot_option_def + OclValid_def invalid_def true_def null_def StrongEq_def) + + +lemma foundation10: +"\ \ \ x \ \ \ \ y \ (\ \ (x and y)) = ( (\ \ x) \ (\ \ y))" +apply(simp add: def_split_local) +by(auto simp: OclAnd_def OclValid_def invalid_def + true_def null_def StrongEq_def null_fun_def null_option_def bot_option_def + split:bool.split_asm) + + +lemma foundation11: +"\ \ \ x \ \ \ \ y \ (\ \ (x or y)) = ( (\ \ x) \ (\ \ y))" +apply(simp add: def_split_local) +by(auto simp: OclNot_def OclOr_def OclAnd_def OclValid_def invalid_def + true_def null_def StrongEq_def null_fun_def null_option_def bot_option_def + split:bool.split_asm bool.split) + + + +lemma foundation12: +"\ \ \ x \ \ \ \ y \ (\ \ (x implies y)) = ( (\ \ x) \ (\ \ y))" +apply(simp add: def_split_local) +by(auto simp: OclNot_def OclOr_def OclAnd_def OclImplies_def bot_option_def + OclValid_def invalid_def true_def null_def StrongEq_def null_fun_def null_option_def + split:bool.split_asm bool.split) + +lemma foundation13:"(\ \ A \ true) = (\ \ A)" +by(auto simp: OclNot_def OclValid_def invalid_def true_def null_def StrongEq_def + split:bool.split_asm bool.split) + +lemma foundation14:"(\ \ A \ false) = (\ \ not A)" +by(auto simp: OclNot_def OclValid_def invalid_def false_def true_def null_def StrongEq_def + split:bool.split_asm bool.split option.split) + +lemma foundation15:"(\ \ A \ invalid) = (\ \ not(\ A))" +by(auto simp: OclNot_def OclValid_def valid_def invalid_def false_def true_def null_def + StrongEq_def bot_option_def null_fun_def null_option_def bot_option_def bot_fun_def + split:bool.split_asm bool.split option.split) + + +(* ... and the usual rules on strictness, definedness propoagation, and cp ... *) +lemma foundation16: "\ \ (\ X) = (X \ \ bot \ X \ \ null)" +by(auto simp: OclValid_def defined_def false_def true_def bot_fun_def null_fun_def + split:split_if_asm) + +(* correcter rule; the previous is deprecated *) +lemma foundation16': "(\ \ (\ X)) = (X \ \ invalid \ \ X \ \ null \)" +apply(simp add:invalid_def null_def null_fun_def) +by(auto simp: OclValid_def defined_def false_def true_def bot_fun_def null_fun_def + split:split_if_asm) + +lemmas foundation17 = foundation16[THEN iffD1,standard] +(* correcter rule; the previous is deprecated *) +lemmas foundation17' = foundation16'[THEN iffD1,standard] + +lemma foundation18: "\ \ (\ X) = (X \ \ invalid \)" +by(auto simp: OclValid_def valid_def false_def true_def bot_fun_def invalid_def + split:split_if_asm) + +(*legacy*) +lemma foundation18': "\ \ (\ X) = (X \ \ bot)" +by(auto simp: OclValid_def valid_def false_def true_def bot_fun_def + split:split_if_asm) + + +lemmas foundation19 = foundation18[THEN iffD1,standard] + +lemma foundation20 : "\ \ (\ X) \ \ \ \ X" +by(simp add: foundation18 foundation16 invalid_def) + +lemma foundation21: "(not A \ not B) = (A \ B)" +by(rule ext, auto simp: OclNot_def StrongEq_def + split: bool.split_asm HOL.split_if_asm option.split) + +lemma foundation22: "(\ \ (X \ Y)) = (X \ = Y \)" +by(auto simp: StrongEq_def OclValid_def true_def) + +lemma foundation23: "(\ \ P) = (\ \ (\ _ . P \))" +by(auto simp: OclValid_def true_def) + +lemmas cp_validity=foundation23 + +lemma foundation24:"(\ \ not(X \ Y)) = (X \ \ Y \)" +by(simp add: StrongEq_def OclValid_def OclNot_def true_def) + + +lemma defined_not_I : "\ \ \ (x) \ \ \ \ (not x)" + by(auto simp: OclNot_def null_def invalid_def defined_def valid_def OclValid_def + true_def false_def bot_option_def null_option_def null_fun_def bot_fun_def + split: option.split_asm HOL.split_if_asm) + +lemma valid_not_I : "\ \ \ (x) \ \ \ \ (not x)" + by(auto simp: OclNot_def null_def invalid_def defined_def valid_def OclValid_def + true_def false_def bot_option_def null_option_def null_fun_def bot_fun_def + split: option.split_asm option.split HOL.split_if_asm) + +lemma defined_and_I : "\ \ \ (x) \ \ \ \ (y) \ \ \ \ (x and y)" + apply(simp add: OclAnd_def null_def invalid_def defined_def valid_def OclValid_def + true_def false_def bot_option_def null_option_def null_fun_def bot_fun_def + split: option.split_asm HOL.split_if_asm) + apply(auto simp: null_option_def split: bool.split) + by(case_tac "ya",simp_all) + +lemma valid_and_I : "\ \ \ (x) \ \ \ \ (y) \ \ \ \ (x and y)" + apply(simp add: OclAnd_def null_def invalid_def defined_def valid_def OclValid_def + true_def false_def bot_option_def null_option_def null_fun_def bot_fun_def + split: option.split_asm HOL.split_if_asm) + by(auto simp: null_option_def split: option.split bool.split) + + + +subsection{* Local Judgements and Strong Equality *} + +lemma StrongEq_L_refl: "\ \ (x \ x)" +by(simp add: OclValid_def StrongEq_def) + + +lemma StrongEq_L_sym: "\ \ (x \ y) \ \ \ (y \ x)" +by(simp add: StrongEq_sym) + +lemma StrongEq_L_trans: "\ \ (x \ y) \ \ \ (y \ z) \ \ \ (x \ z)" +by(simp add: OclValid_def StrongEq_def true_def) + + + +text{* In order to establish substitutivity (which does not +hold in general HOL formulas) we introduce the following +predicate that allows for a calculus of the necessary side-conditions.*} +definition cp :: "(('\,'\) val \ ('\,'\) val) \ bool" +where "cp P \ (\ f. \ X \. P X \ = f (X \) \)" + + +text{* The rule of substitutivity in Featherweight OCL holds only +for context-passing expressions, \ie those that pass +the context @{text "\"} without changing it. Fortunately, all +operators of the OCL language satisfy this property +(but not all HOL operators).*} + +lemma StrongEq_L_subst1: "\ \. cp P \ \ \ (x \ y) \ \ \ (P x \ P y)" +by(auto simp: OclValid_def StrongEq_def true_def cp_def) + +lemma StrongEq_L_subst2: +"\ \. cp P \ \ \ (x \ y) \ \ \ (P x) \ \ \ (P y)" +by(auto simp: OclValid_def StrongEq_def true_def cp_def) + +lemma StrongEq_L_subst2_rev: "\ \ y \ x \ cp P \ \ \ P x \ \ \ P y" +apply(erule StrongEq_L_subst2) +apply(erule StrongEq_L_sym) +by assumption + +lemma StrongEq_L_subst3: +assumes cp: "cp P" +and eq: "\ \ x \ y" +shows "(\ \ P x) = (\ \ P y)" +apply(rule iffI) +apply(rule OCL_core.StrongEq_L_subst2[OF cp,OF eq],simp) +apply(rule OCL_core.StrongEq_L_subst2[OF cp,OF eq[THEN StrongEq_L_sym]],simp) +done + + +lemma cpI1: +"(\ X \. f X \ = f(\_. X \) \) \ cp P \ cp(\X. f (P X))" +apply(auto simp: true_def cp_def) +apply(rule exI, (rule allI)+) +by(erule_tac x="P X" in allE, auto) + +lemma cpI2: +"(\ X Y \. f X Y \ = f(\_. X \)(\_. Y \) \) \ + cp P \ cp Q \ cp(\X. f (P X) (Q X))" +apply(auto simp: true_def cp_def) +apply(rule exI, (rule allI)+) +by(erule_tac x="P X" in allE, auto) + +lemma cpI3: +"(\ X Y Z \. f X Y Z \ = f(\_. X \)(\_. Y \)(\_. Z \) \) \ + cp P \ cp Q \ cp R \ cp(\X. f (P X) (Q X) (R X))" +apply(auto simp: cp_def) +apply(rule exI, (rule allI)+) +by(erule_tac x="P X" in allE, auto) + +lemma cpI4: +"(\ W X Y Z \. f W X Y Z \ = f(\_. W \)(\_. X \)(\_. Y \)(\_. Z \) \) \ + cp P \ cp Q \ cp R \ cp S \ cp(\X. f (P X) (Q X) (R X) (S X))" +apply(auto simp: cp_def) +apply(rule exI, (rule allI)+) +by(erule_tac x="P X" in allE, auto) + +lemma cp_const : "cp(\_. c)" + by (simp add: cp_def, fast) + +lemma cp_id : "cp(\X. X)" + by (simp add: cp_def, fast) + +lemmas cp_intro[intro!,simp,code_unfold] = + cp_const + cp_id + cp_defined[THEN allI[THEN allI[THEN cpI1], of defined]] + cp_valid[THEN allI[THEN allI[THEN cpI1], of valid]] + cp_OclNot[THEN allI[THEN allI[THEN cpI1], of not]] + cp_OclAnd[THEN allI[THEN allI[THEN allI[THEN cpI2]], of "op and"]] + cp_OclOr[THEN allI[THEN allI[THEN allI[THEN cpI2]], of "op or"]] + cp_OclImplies[THEN allI[THEN allI[THEN allI[THEN cpI2]], of "op implies"]] + cp_StrongEq[THEN allI[THEN allI[THEN allI[THEN cpI2]], + of "StrongEq"]] + +subsection{* Laws to Establish Definedness ($\delta$-closure) *} + +text{* For the logical connectives, we have --- beyond +@{thm foundation6} --- the following facts: *} +lemma OclNot_defargs: +"\ \ (not P) \ \ \ \ P" +by(auto simp: OclNot_def OclValid_def true_def invalid_def defined_def false_def + bot_fun_def bot_option_def null_fun_def null_option_def + split: bool.split_asm HOL.split_if_asm option.split option.split_asm) + +lemma OclNot_contrapos_nn: + assumes "\ \ \ A" + assumes "\ \ not B" + assumes "\ \ A \ \ \ B" + shows "\ \ not A" +proof - + have change_not : "\a b. (not a \ = b \) = (a \ = not b \)" + by (metis OclNot_not cp_OclNot) + show ?thesis + apply(insert assms, simp add: OclValid_def, subst change_not, subst (asm) change_not) + apply(simp add: OclNot_def true_def) + by (metis OclValid_def bool_split defined_def false_def foundation2 true_def + bot_fun_def invalid_def) +qed + +text{* So far, we have only one strict Boolean predicate (-family): the strict equality. *} + +section{* Miscellaneous *} + +subsection{* OCL's if then else endif *} + +definition OclIf :: "[('\)Boolean , ('\,'\::null) val, ('\,'\) val] \ ('\,'\) val" + ("if (_) then (_) else (_) endif" [10,10,10]50) +where "(if C then B\<^sub>1 else B\<^sub>2 endif) = (\ \. if (\ C) \ = true \ + then (if (C \) = true \ + then B\<^sub>1 \ + else B\<^sub>2 \) + else invalid \)" + + +lemma cp_OclIf:"((if C then B\<^sub>1 else B\<^sub>2 endif) \ = + (if (\ _. C \) then (\ _. B\<^sub>1 \) else (\ _. B\<^sub>2 \) endif) \)" +by(simp only: OclIf_def, subst cp_defined, rule refl) + +lemmas cp_intro'[intro!,simp,code_unfold] = + cp_intro + cp_OclIf[THEN allI[THEN allI[THEN allI[THEN allI[THEN cpI3]]], of "OclIf"]] + +lemma OclIf_invalid [simp]: "(if invalid then B\<^sub>1 else B\<^sub>2 endif) = invalid" +by(rule ext, auto simp: OclIf_def) + +lemma OclIf_null [simp]: "(if null then B\<^sub>1 else B\<^sub>2 endif) = invalid" +by(rule ext, auto simp: OclIf_def) + +lemma OclIf_true [simp]: "(if true then B\<^sub>1 else B\<^sub>2 endif) = B\<^sub>1" +by(rule ext, auto simp: OclIf_def) + +lemma OclIf_true' [simp]: "\ \ P \ (if P then B\<^sub>1 else B\<^sub>2 endif)\ = B\<^sub>1 \" +apply(subst cp_OclIf,auto simp: OclValid_def) +by(simp add:cp_OclIf[symmetric]) + +lemma OclIf_false [simp]: "(if false then B\<^sub>1 else B\<^sub>2 endif) = B\<^sub>2" +by(rule ext, auto simp: OclIf_def) + +lemma OclIf_false' [simp]: "\ \ not P \ (if P then B\<^sub>1 else B\<^sub>2 endif)\ = B\<^sub>2 \" +apply(subst cp_OclIf) +apply(auto simp: foundation14[symmetric] foundation22) +by(auto simp: cp_OclIf[symmetric]) + + +lemma OclIf_idem1[simp]:"(if \ X then A else A endif) = A" +by(rule ext, auto simp: OclIf_def) + +lemma OclIf_idem2[simp]:"(if \ X then A else A endif) = A" +by(rule ext, auto simp: OclIf_def) + +lemma OclNot_if[simp]: +"not(if P then C else E endif) = (if P then not C else not E endif)" + (* non-trivial but elementary *) + apply(rule OclNot_inject, simp) + apply(rule ext) + apply(subst cp_OclNot, simp add: OclIf_def) + apply(subst cp_OclNot[symmetric])+ +by simp + + +subsection{* A Side-calculus for (Boolean) Constant Terms *} + +definition "const X \ \ \ \'. X \ = X \'" + +lemma const_charn: "const X \ X \ = X \'" +by(auto simp: const_def) + +lemma const_subst: + assumes const_X: "const X" + and const_Y: "const Y" + and eq : "X \ = Y \" + and cp_P: "cp P" + and pp : "P Y \ = P Y \'" + shows "P X \ = P X \'" +proof - + have A: "\Y. P Y \ = P (\_. Y \) \" + apply(insert cp_P, unfold cp_def) + apply(elim exE, erule_tac x=Y in allE', erule_tac x=\ in allE) + apply(erule_tac x="(\_. Y \)" in allE, erule_tac x=\ in allE) + by simp + have B: "\Y. P Y \' = P (\_. Y \') \'" + apply(insert cp_P, unfold cp_def) + apply(elim exE, erule_tac x=Y in allE', erule_tac x=\' in allE) + apply(erule_tac x="(\_. Y \')" in allE, erule_tac x=\' in allE) + by simp + have C: "X \' = Y \'" + apply(rule trans, subst const_charn[OF const_X],rule eq) + by(rule const_charn[OF const_Y]) + show ?thesis + apply(subst A, subst B, simp add: eq C) + apply(subst A[symmetric],subst B[symmetric]) + by(simp add:pp) +qed + + +lemma const_imply2 : + assumes "\\1 \2. P \1 = P \2 \ Q \1 = Q \2" + shows "const P \ const Q" +by(simp add: const_def, insert assms, blast) + +lemma const_imply3 : + assumes "\\1 \2. P \1 = P \2 \ Q \1 = Q \2 \ R \1 = R \2" + shows "const P \ const Q \ const R" +by(simp add: const_def, insert assms, blast) + +lemma const_imply4 : + assumes "\\1 \2. P \1 = P \2 \ Q \1 = Q \2 \ R \1 = R \2 \ S \1 = S \2" + shows "const P \ const Q \ const R \ const S" +by(simp add: const_def, insert assms, blast) + +lemma const_lam : "const (\_. e)" +by(simp add: const_def) + + +lemma const_true : "const true" +by(simp add: const_def true_def) + +lemma const_false : "const false" +by(simp add: const_def false_def) + +lemma const_null : "const null" +by(simp add: const_def null_fun_def) + +lemma const_invalid : "const invalid" +by(simp add: const_def invalid_def) + +lemma const_bot : "const bot" +by(simp add: const_def bot_fun_def) + + + +lemma const_defined : + assumes "const X" + shows "const (\ X)" +by(rule const_imply2[OF _ assms], + simp add: defined_def false_def true_def bot_fun_def bot_option_def null_fun_def null_option_def) + +lemma const_valid : + assumes "const X" + shows "const (\ X)" +by(rule const_imply2[OF _ assms], + simp add: valid_def false_def true_def bot_fun_def null_fun_def assms) + +lemma const_OclValid1: + assumes "const x" + shows "(\ \ \ x) = (\' \ \ x)" + apply(simp add: OclValid_def) + apply(subst const_defined[OF assms, THEN const_charn]) + by(simp add: true_def) + +lemma const_OclValid2: + assumes "const x" + shows "(\ \ \ x) = (\' \ \ x)" + apply(simp add: OclValid_def) + apply(subst const_valid[OF assms, THEN const_charn]) + by(simp add: true_def) + + +lemma const_OclAnd : + assumes "const X" + assumes "const X'" + shows "const (X and X')" +by(rule const_imply3[OF _ assms], subst (1 2) cp_OclAnd, simp add: assms OclAnd_def) + + + +lemma const_OclNot : + assumes "const X" + shows "const (not X)" +by(rule const_imply2[OF _ assms],subst cp_OclNot,simp add: assms OclNot_def) + +lemma const_OclOr : + assumes "const X" + assumes "const X'" + shows "const (X or X')" +by(simp add: assms OclOr_def const_OclNot const_OclAnd) + +lemma const_OclImplies : + assumes "const X" + assumes "const X'" + shows "const (X implies X')" +by(simp add: assms OclImplies_def const_OclNot const_OclOr) + +lemma const_StrongEq: + assumes "const X" + assumes "const X'" + shows "const(X \ X')" + apply(simp only: StrongEq_def const_def, intro allI) + apply(subst assms(1)[THEN const_charn]) + apply(subst assms(2)[THEN const_charn]) + by simp + +lemma const_OclIf : + assumes "const B" + and "const C1" + and "const C2" + shows "const (if B then C1 else C2 endif)" + apply(rule const_imply4[OF _ assms], + subst (1 2) cp_OclIf, simp only: OclIf_def cp_defined[symmetric]) + apply(simp add: const_defined[OF assms(1), simplified const_def, THEN spec, THEN spec] + const_true[simplified const_def, THEN spec, THEN spec] + assms[simplified const_def, THEN spec, THEN spec] + const_invalid[simplified const_def, THEN spec, THEN spec]) +by (metis (no_types) OCL_core.bot_fun_def OclValid_def const_def const_true defined_def foundation17 + null_fun_def) + +lemmas const_ss = const_bot const_null const_invalid const_false const_true const_lam + const_defined const_valid const_StrongEq const_OclNot const_OclAnd + const_OclOr const_OclImplies const_OclIf +end diff --git a/OCL_lib.thy b/OCL_lib.thy new file mode 100644 index 0000000..4d30614 --- /dev/null +++ b/OCL_lib.thy @@ -0,0 +1,3172 @@ +(***************************************************************************** + * Featherweight-OCL --- A Formal Semantics for UML-OCL Version OCL 2.4 + * for the OMG Standard. + * http://www.brucker.ch/projects/hol-testgen/ + * + * OCL_lib.thy --- Library definitions. + * This file is part of HOL-TestGen. + * + * Copyright (c) 2012-2013 Université Paris-Sud, France + * 2013 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. + ******************************************************************************) + +header{* Formalization II: Library Definitions *} + +theory OCL_lib +imports OCL_core +begin + +text {* +The structure of this chapter roughly follows the structure of Chapter +10 of the OCL standard~\cite{omg:ocl:2012}, which introduces the OCL +Library. + *} + +section{* Basic Types: Void and Integer *} +subsection{* The Construction of the Void Type *} +type_synonym ('\)Void = "('\,unit option) val" +(* For technical reasons, the type does not contain to the null-class yet. *) +text {* This \emph{minimal} OCL type contains only two elements: +@{term "invalid"} and @{term "null"}. +@{term "Void"} could initially be defined as @{typ "unit option option"}, +however the cardinal of this type is more than two, so it would have the cost to consider + @{text "Some None"} and @{text "Some (Some ())"} seemingly everywhere.*} + + +subsection{* The Construction of the Integer Type *} +text{* Since @{term "Integer"} is again a basic type, we define its semantic domain +as the valuations over @{typ "int option option"}. *} +type_synonym ('\)Integer = "('\,int option option) val" + +text{* Although the remaining part of this library reasons about +integers abstractly, we provide here as example some convenient shortcuts. *} + +definition OclInt0 ::"('\)Integer" ("\") +where "\ = (\ _ . \\0::int\\)" + +definition OclInt1 ::"('\)Integer" ("\") +where "\ = (\ _ . \\1::int\\)" + +definition OclInt2 ::"('\)Integer" ("\") +where "\ = (\ _ . \\2::int\\)" + +definition OclInt3 ::"('\)Integer" ("\") +where "\ = (\ _ . \\3::int\\)" + +definition OclInt4 ::"('\)Integer" ("\") +where "\ = (\ _ . \\4::int\\)" + +definition OclInt5 ::"('\)Integer" ("\") +where "\ = (\ _ . \\5::int\\)" + +definition OclInt6 ::"('\)Integer" ("\") +where "\ = (\ _ . \\6::int\\)" + +definition OclInt7 ::"('\)Integer" ("\") +where "\ = (\ _ . \\7::int\\)" + +definition OclInt8 ::"('\)Integer" ("\") +where "\ = (\ _ . \\8::int\\)" + +definition OclInt9 ::"('\)Integer" ("\") +where "\ = (\ _ . \\9::int\\)" + +definition OclInt10 ::"('\)Integer" ("\\") +where "\\ = (\ _ . \\10::int\\)" + +subsection{* Validity and Definedness Properties *} + +lemma "\(null::('\)Integer) = false" by simp +lemma "\(null::('\)Integer) = true" by simp + +lemma [simp,code_unfold]: "\ (\_. \\n\\) = true" +by(simp add:defined_def true_def + bot_fun_def bot_option_def null_fun_def null_option_def) + +lemma [simp,code_unfold]: "\ (\_. \\n\\) = true" +by(simp add:valid_def true_def + bot_fun_def bot_option_def) + +(* ecclectic proofs to make examples executable *) +lemma [simp,code_unfold]: "\ \ = true" by(simp add:OclInt0_def) +lemma [simp,code_unfold]: "\ \ = true" by(simp add:OclInt0_def) +lemma [simp,code_unfold]: "\ \ = true" by(simp add:OclInt1_def) +lemma [simp,code_unfold]: "\ \ = true" by(simp add:OclInt1_def) +lemma [simp,code_unfold]: "\ \ = true" by(simp add:OclInt2_def) +lemma [simp,code_unfold]: "\ \ = true" by(simp add:OclInt2_def) +lemma [simp,code_unfold]: "\ \ = true" by(simp add:OclInt6_def) +lemma [simp,code_unfold]: "\ \ = true" by(simp add:OclInt6_def) +lemma [simp,code_unfold]: "\ \ = true" by(simp add:OclInt8_def) +lemma [simp,code_unfold]: "\ \ = true" by(simp add:OclInt8_def) +lemma [simp,code_unfold]: "\ \ = true" by(simp add:OclInt9_def) +lemma [simp,code_unfold]: "\ \ = true" by(simp add:OclInt9_def) + + +subsection{* Arithmetical Operations on Integer *} + +subsubsection{* Definition *} +text{* Here is a common case of a built-in operation on built-in types. +Note that the arguments must be both defined (non-null, non-bot). *} +text{* Note that we can not follow the lexis of the OCL Standard for Isabelle +technical reasons; these operators are heavily overloaded in the HOL library +that a further overloading would lead to heavy technical buzz in this +document. +*} +definition OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r ::"('\)Integer \ ('\)Integer \ ('\)Integer" (infix "`+" 40) +where "x `+ y \ \ \. if (\ x) \ = true \ \ (\ y) \ = true \ + then \\\\x \\\ + \\y \\\\\ + else invalid \ " + +definition OclLess\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r ::"('\)Integer \ ('\)Integer \ ('\)Boolean" (infix "`<" 40) +where "x `< y \ \ \. if (\ x) \ = true \ \ (\ y) \ = true \ + then \\\\x \\\ < \\y \\\\\ + else invalid \ " + +definition OclLe\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r ::"('\)Integer \ ('\)Integer \ ('\)Boolean" (infix "`\" 40) +where "x `\ y \ \ \. if (\ x) \ = true \ \ (\ y) \ = true \ + then \\\\x \\\ \ \\y \\\\\ + else invalid \ " + +subsubsection{* Basic Properties *} + +lemma OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_commute: "(X `+ Y) = (Y `+ X)" + by(rule ext,auto simp:true_def false_def OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_def invalid_def + split: option.split option.split_asm + bool.split bool.split_asm) + +subsubsection{* Execution with Invalid or Null or Zero as Argument *} + +lemma OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_strict1[simp,code_unfold] : "(x `+ invalid) = invalid" +by(rule ext, simp add: OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_def true_def false_def) + +lemma OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_strict2[simp,code_unfold] : "(invalid `+ x) = invalid" +by(rule ext, simp add: OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_def true_def false_def) + +lemma [simp,code_unfold] : "(x `+ null) = invalid" +by(rule ext, simp add: OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_def true_def false_def) + +lemma [simp,code_unfold] : "(null `+ x) = invalid" +by(rule ext, simp add: OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_def true_def false_def) + +lemma OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_zero1[simp,code_unfold] : +"(x `+ \) = (if \ x and not (\ x) then invalid else x endif)" + proof (rule ext, rename_tac \, case_tac "(\ x and not (\ x)) \ = true \") + fix \ show "(\ x and not (\ x)) \ = true \ \ + (x `+ \) \ = (if \ x and not (\ x) then invalid else x endif) \" + apply(subst OclIf_true', simp add: OclValid_def) + by (metis OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_def OclNot_defargs OclValid_def foundation5 foundation9) + apply_end assumption + next fix \ + have A: "\\. (\ \ not (\ x and not (\ x))) = (x \ = invalid \ \ \ \ \ x)" + by (metis OclNot_not OclOr_def defined5 defined6 defined_not_I foundation11 foundation18' + foundation6 foundation7 foundation9 invalid_def) + have B: "\ \ \ x \ \\\\x \\\\\ = x \" + apply(cases "x \", metis bot_option_def foundation17) + apply(rename_tac x', case_tac x', metis bot_option_def foundation16 null_option_def) + by(simp) + show "\ \ not (\ x and not (\ x)) \ + (x `+ \) \ = (if \ x and not (\ x) then invalid else x endif) \" + apply(subst OclIf_false', simp, simp add: A, auto simp: OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_def OclInt0_def) + (* *) + apply (metis OclValid_def foundation19 foundation20) + apply(simp add: B) + by(simp add: OclValid_def) + apply_end(metis OclValid_def defined5 defined6 defined_and_I defined_not_I foundation9) +qed + +lemma OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_zero2[simp,code_unfold] : +"(\ `+ x) = (if \ x and not (\ x) then invalid else x endif)" +by(subst OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_commute, simp) + +subsubsection{* Context Passing *} + +lemma cp_OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r:"(X `+ Y) \ = ((\ _. X \) `+ (\ _. Y \)) \" +by(simp add: OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_def cp_defined[symmetric]) + +lemma cp_OclLess\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r:"(X `< Y) \ = ((\ _. X \) `< (\ _. Y \)) \" +by(simp add: OclLess\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_def cp_defined[symmetric]) + +lemma cp_OclLe\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r:"(X `\ Y) \ = ((\ _. X \) `\ (\ _. Y \)) \" +by(simp add: OclLe\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_def cp_defined[symmetric]) + +subsubsection{* Test Statements *} +text{* Here follows a list of code-examples, that explain the meanings +of the above definitions by compilation to code and execution to @{term "True"}.*} + +value " \ \ ( \ `\ \\ )" +value " \ \ (( \ `+ \ ) `\ \\ )" +value "\(\ \ (( \ `+ ( \ `+ \ )) `< \\ ))" +value " \ \ not (\ (null `+ \)) " + +section{* Fundamental Predicates on Basic Types: Strict Equality *} + +subsection{* Definition *} + +text{* The last basic operation belonging to the fundamental infrastructure +of a value-type in OCL is the weak equality, which is defined similar +to the @{typ "('\)Boolean"}-case as strict extension of the strong equality:*} +defs StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r[code_unfold] : + "(x::('\)Integer) \ y \ \ \. if (\ x) \ = true \ \ (\ y) \ = true \ + then (x \ y) \ + else invalid \" + +value "\ \ \ <> \" +value "\ \ \ <> \" +value "\ \ \ \ \" + +subsection{* Logic and Algebraic Layer on Basic Types *} + +subsubsection{* Validity and Definedness Properties (I) *} + +lemma StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n_defined_args_valid: +"(\ \ \((x::('\)Boolean) \ y)) = ((\ \(\ x)) \ (\ \(\ y)))" +by(auto simp: StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n OclValid_def true_def valid_def false_def StrongEq_def + defined_def invalid_def null_fun_def bot_fun_def null_option_def bot_option_def + split: bool.split_asm HOL.split_if_asm option.split) + +lemma StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_defined_args_valid: +"(\ \ \((x::('\)Integer) \ y)) = ((\ \(\ x)) \ (\ \(\ y)))" +by(auto simp: StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r OclValid_def true_def valid_def false_def StrongEq_def + defined_def invalid_def null_fun_def bot_fun_def null_option_def bot_option_def + split: bool.split_asm HOL.split_if_asm option.split) + +subsubsection{* Validity and Definedness Properties (II) *} + +lemma StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n_defargs: +"\ \ ((x::('\)Boolean) \ y) \ (\ \ (\ x)) \ (\ \(\ y))" +by(simp add: StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n OclValid_def true_def invalid_def + bot_option_def + split: bool.split_asm HOL.split_if_asm) + +lemma StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_defargs: +"\ \ ((x::('\)Integer) \ y) \ (\ \ (\ x)) \ (\ \ (\ y))" +by(simp add: StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r OclValid_def true_def invalid_def valid_def bot_option_def + split: bool.split_asm HOL.split_if_asm) + +subsubsection{* Validity and Definedness Properties (III) Miscellaneous *} + +lemma StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n_strict'' : "\ ((x::('\)Boolean) \ y) = (\(x) and \(y))" +by(auto intro!: transform2_rev defined_and_I simp:foundation10 StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n_defined_args_valid) + +lemma StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_strict'' : "\ ((x::('\)Integer) \ y) = (\(x) and \(y))" +by(auto intro!: transform2_rev defined_and_I simp:foundation10 StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_defined_args_valid) + +(* Probably not very useful *) +lemma StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_strict : + assumes A: "\ (x::('\)Integer) = true" + and B: "\ y = true" + shows "\ (x \ y) = true" + apply(insert A B) + apply(rule ext, simp add: StrongEq_def StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r true_def valid_def defined_def + bot_fun_def bot_option_def) + done + + +(* Probably not very useful *) +lemma StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_strict' : + assumes A: "\ (((x::('\)Integer)) \ y) = true" + shows "\ x = true \ \ y = true" + apply(insert A, rule conjI) + apply(rule ext, rename_tac \, drule_tac x=\ in fun_cong) + prefer 2 + apply(rule ext, rename_tac \, drule_tac x=\ in fun_cong) + apply(simp_all add: StrongEq_def StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r + false_def true_def valid_def defined_def) + apply(case_tac "y \", auto) + apply(simp_all add: true_def invalid_def bot_fun_def) + done + +subsubsection{* Reflexivity *} + +lemma StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n_refl[simp,code_unfold] : +"((x::('\)Boolean) \ x) = (if (\ x) then true else invalid endif)" +by(rule ext, simp add: StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n OclIf_def) + +lemma StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_refl[simp,code_unfold] : +"((x::('\)Integer) \ x) = (if (\ x) then true else invalid endif)" +by(rule ext, simp add: StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r OclIf_def) + +subsubsection{* Execution with Invalid or Null as Argument *} + +lemma StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n_strict1[simp,code_unfold] : "((x::('\)Boolean) \ invalid) = invalid" +by(rule ext, simp add: StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n true_def false_def) + +lemma StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n_strict2[simp,code_unfold] : "(invalid \ (x::('\)Boolean)) = invalid" +by(rule ext, simp add: StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n true_def false_def) + +lemma StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_strict1[simp,code_unfold] : "((x::('\)Integer) \ invalid) = invalid" +by(rule ext, simp add: StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r true_def false_def) + +lemma StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_strict2[simp,code_unfold] : "(invalid \ (x::('\)Integer)) = invalid" +by(rule ext, simp add: StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r true_def false_def) + +lemma integer_non_null [simp]: "((\_. \\n\\) \ (null::('\)Integer)) = false" +by(rule ext,auto simp: StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r valid_def + bot_fun_def bot_option_def null_fun_def null_option_def StrongEq_def) + +lemma null_non_integer [simp]: "((null::('\)Integer) \ (\_. \\n\\)) = false" +by(rule ext,auto simp: StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r valid_def + bot_fun_def bot_option_def null_fun_def null_option_def StrongEq_def) + +lemma OclInt0_non_null [simp,code_unfold]: "(\ \ null) = false" by(simp add: OclInt0_def) +lemma null_non_OclInt0 [simp,code_unfold]: "(null \ \) = false" by(simp add: OclInt0_def) +lemma OclInt1_non_null [simp,code_unfold]: "(\ \ null) = false" by(simp add: OclInt1_def) +lemma null_non_OclInt1 [simp,code_unfold]: "(null \ \) = false" by(simp add: OclInt1_def) +lemma OclInt2_non_null [simp,code_unfold]: "(\ \ null) = false" by(simp add: OclInt2_def) +lemma null_non_OclInt2 [simp,code_unfold]: "(null \ \) = false" by(simp add: OclInt2_def) +lemma OclInt6_non_null [simp,code_unfold]: "(\ \ null) = false" by(simp add: OclInt6_def) +lemma null_non_OclInt6 [simp,code_unfold]: "(null \ \) = false" by(simp add: OclInt6_def) +lemma OclInt8_non_null [simp,code_unfold]: "(\ \ null) = false" by(simp add: OclInt8_def) +lemma null_non_OclInt8 [simp,code_unfold]: "(null \ \) = false" by(simp add: OclInt8_def) +lemma OclInt9_non_null [simp,code_unfold]: "(\ \ null) = false" by(simp add: OclInt9_def) +lemma null_non_OclInt9 [simp,code_unfold]: "(null \ \) = false" by(simp add: OclInt9_def) + + +(* plus all the others ...*) + +subsubsection{* Const *} + +lemma [simp,code_unfold]: "const(\)" by(simp add: const_ss OclInt0_def) +lemma [simp,code_unfold]: "const(\)" by(simp add: const_ss OclInt1_def) +lemma [simp,code_unfold]: "const(\)" by(simp add: const_ss OclInt2_def) +lemma [simp,code_unfold]: "const(\)" by(simp add: const_ss OclInt6_def) +lemma [simp,code_unfold]: "const(\)" by(simp add: const_ss OclInt8_def) +lemma [simp,code_unfold]: "const(\)" by(simp add: const_ss OclInt9_def) + + +subsubsection{* Behavior vs StrongEq *} + +lemma StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n_vs_StrongEq: +"\ \(\ x) \ \ \(\ y) \ (\ \ (((x::('\)Boolean) \ y) \ (x \ y)))" +apply(simp add: StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n OclValid_def) +apply(subst cp_StrongEq[of _ "(x \ y)"]) +by simp + + +lemma StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_vs_StrongEq: +"\ \(\ x) \ \ \(\ y) \ (\ \ (((x::('\)Integer) \ y) \ (x \ y)))" +apply(simp add: StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r OclValid_def) +apply(subst cp_StrongEq[of _ "(x \ y)"]) +by simp + + +subsubsection{* Context Passing *} + +lemma cp_StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n: +"((X::('\)Boolean) \ Y) \ = ((\ _. X \) \ (\ _. Y \)) \" +by(auto simp: StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n StrongEq_def defined_def valid_def cp_defined[symmetric]) + +lemma cp_StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r: +"((X::('\)Integer) \ Y) \ = ((\ _. X \) \ (\ _. Y \)) \" +by(auto simp: StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r StrongEq_def valid_def cp_defined[symmetric]) + + +lemmas cp_intro'[intro!,simp,code_unfold] = + cp_intro' + cp_StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n[THEN allI[THEN allI[THEN allI[THEN cpI2]], of "StrictRefEq"]] + cp_StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r[THEN allI[THEN allI[THEN allI[THEN cpI2]], of "StrictRefEq"]] + cp_OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r[THEN allI[THEN allI[THEN allI[THEN cpI2]], of "OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r"]] + cp_OclLess\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r[THEN allI[THEN allI[THEN allI[THEN cpI2]], of "OclLess\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r"]] + cp_OclLe\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r[THEN allI[THEN allI[THEN allI[THEN cpI2]], of "OclLe\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r"]] + + +subsection{* Test Statements on Basic Types. *} + +text{* Here follows a list of code-examples, that explain the meanings +of the above definitions by compilation to code and execution to @{term "True"}.*} + +text{* Elementary computations on Booleans *} +value "\ \ \(true)" +value "\ \ \(false)" +value "\(\ \ \(null))" +value "\(\ \ \(invalid))" +value "\ \ \((null::('\)Boolean))" +value "\(\ \ \(invalid))" +value "\ \ (true and true)" +value "\ \ (true and true \ true)" +value "\ \ ((null or null) \ null)" +value "\ \ ((null or null) \ null)" +value "\ \ ((true \ false) \ false)" +value "\ \ ((invalid \ false) \ false)" +value "\ \ ((invalid \ false) \ invalid)" + + +text{* Elementary computations on Integer *} +value " \ \ \ \" +value " \ \ \ \" +value " \ \ \ (null::('\)Integer)" +value " \ \ (invalid \ invalid)" +value " \ \ (null \ null)" +value " \ \ (\ \ \)" +value "\(\ \ (\ \ \\))" +value "\(\ \ (invalid \ \\))" +value "\(\ \ (null \ \\))" +value "\(\ \ (invalid \ (invalid::('\)Integer)))" (* Without typeconstraint not executable.*) +value "\(\ \ \ (invalid \ (invalid::('\)Integer)))" (* Without typeconstraint not executable.*) +value "\(\ \ (invalid <> (invalid::('\)Integer)))" (* Without typeconstraint not executable.*) +value "\(\ \ \ (invalid <> (invalid::('\)Integer)))" (* Without typeconstraint not executable.*) +value " \ \ (null \ (null::('\)Integer) )" (* Without typeconstraint not executable.*) +value " \ \ (null \ (null::('\)Integer) )" (* Without typeconstraint not executable.*) +value " \ \ (\ \ \)" +value "\(\ \ (\ <> \))" +value "\(\ \ (\ \ \\))" +value " \ \ (\ <> \\)" +value "\(\ \ (\ `< null))" +value "\(\ \ (\ (\ `< null)))" + + +section{* Complex Types: The Set-Collection Type (I) Core *} + +subsection{* The Construction of the Set Type *} + +no_notation None ("\") +notation bot ("\") + +text{* For the semantic construction of the collection types, we have two goals: +\begin{enumerate} +\item we want the types to be \emph{fully abstract}, \ie, the type should not + contain junk-elements that are not representable by OCL expressions, and +\item we want a possibility to nest collection types (so, we want the + potential to talking about @{text "Set(Set(Sequences(Pairs(X,Y))))"}). +\end{enumerate} +The former principle rules out the option to define @{text "'\ Set"} just by + @{text "('\, ('\ option option) set) val"}. This would allow sets to contain +junk elements such as @{text "{\}"} which we need to identify with undefinedness +itself. Abandoning fully abstractness of rules would later on produce all sorts +of problems when quantifying over the elements of a type. +However, if we build an own type, then it must conform to our abstract interface +in order to have nested types: arguments of type-constructors must conform to our +abstract interface, and the result type too. +*} + +text{* The core of an own type construction is done via a type + definition which provides the raw-type @{text "'\ Set_0"}. It + is shown that this type ``fits'' indeed into the abstract type + interface discussed in the previous section. *} + +typedef '\ Set_0 ="{X::('\\null) set option option. + X = bot \ X = null \ (\x\\\X\\. x \ bot)}" + by (rule_tac x="bot" in exI, simp) + +instantiation Set_0 :: (null)bot +begin + + definition bot_Set_0_def: "(bot::('a::null) Set_0) \ Abs_Set_0 None" + + instance proof show "\x\'a Set_0. x \ bot" + apply(rule_tac x="Abs_Set_0 \None\" in exI) + apply(simp add:bot_Set_0_def) + apply(subst Abs_Set_0_inject) + apply(simp_all add: bot_Set_0_def + null_option_def bot_option_def) + done + qed +end + + +instantiation Set_0 :: (null)null +begin + + definition null_Set_0_def: "(null::('a::null) Set_0) \ Abs_Set_0 \ None \" + + instance proof show "(null::('a::null) Set_0) \ bot" + apply(simp add:null_Set_0_def bot_Set_0_def) + apply(subst Abs_Set_0_inject) + apply(simp_all add: bot_Set_0_def + null_option_def bot_option_def) + done + qed +end + + +text{* ... and lifting this type to the format of a valuation gives us:*} +type_synonym ('\,'\) Set = "('\, '\ Set_0) val" + +subsection{* Validity and Definedness Properties *} + +text{* Every element in a defined set is valid. *} + +lemma Set_inv_lemma: "\ \ (\ X) \ \x\\\Rep_Set_0 (X \)\\. x \ bot" +apply(insert Rep_Set_0 [of "X \"], simp) +apply(auto simp: OclValid_def defined_def false_def true_def cp_def + bot_fun_def bot_Set_0_def null_Set_0_def null_fun_def + split:split_if_asm) + apply(erule contrapos_pp [of "Rep_Set_0 (X \) = bot"]) + apply(subst Abs_Set_0_inject[symmetric], rule Rep_Set_0, simp) + apply(simp add: Rep_Set_0_inverse bot_Set_0_def bot_option_def) +apply(erule contrapos_pp [of "Rep_Set_0 (X \) = null"]) +apply(subst Abs_Set_0_inject[symmetric], rule Rep_Set_0, simp) +apply(simp add: Rep_Set_0_inverse null_option_def) +by (simp add: bot_option_def) + +lemma Set_inv_lemma' : + assumes x_def : "\ \ \ X" + and e_mem : "e \ \\Rep_Set_0 (X \)\\" + shows "\ \ \ (\_. e)" + apply(rule Set_inv_lemma[OF x_def, THEN ballE[where x = e]]) + apply(simp add: foundation18') +by(simp add: e_mem) + +lemma abs_rep_simp' : + assumes S_all_def : "\ \ \ S" + shows "Abs_Set_0 \\\\Rep_Set_0 (S \)\\\\ = S \" +proof - + have discr_eq_false_true : "\\. (false \ = true \) = False" by(simp add: false_def true_def) + show ?thesis + apply(insert S_all_def, simp add: OclValid_def defined_def) + apply(rule mp[OF Abs_Set_0_induct[where P = "\S. (if S = \ \ \ S = null \ + then false \ else true \) = true \ \ + Abs_Set_0 \\\\Rep_Set_0 S\\\\ = S"]], + rename_tac S') + apply(simp add: Abs_Set_0_inverse discr_eq_false_true) + apply(case_tac S') apply(simp add: bot_fun_def bot_Set_0_def)+ + apply(rename_tac S'', case_tac S'') apply(simp add: null_fun_def null_Set_0_def)+ + done +qed + +lemma S_lift' : + assumes S_all_def : "(\ :: '\ st) \ \ S" + shows "\S'. (\a (_::'\ st). a) ` \\Rep_Set_0 (S \)\\ = (\a (_::'\ st). \a\) ` S'" + apply(rule_tac x = "(\a. \a\) ` \\Rep_Set_0 (S \)\\" in exI) + apply(simp only: image_comp[symmetric]) + apply(simp add: comp_def) + apply(rule image_cong, fast) + (* *) + apply(drule Set_inv_lemma'[OF S_all_def]) +by(case_tac x, (simp add: bot_option_def foundation18')+) + +lemma invalid_set_OclNot_defined [simp,code_unfold]:"\(invalid::('\,'\::null) Set) = false" by simp +lemma null_set_OclNot_defined [simp,code_unfold]:"\(null::('\,'\::null) Set) = false" +by(simp add: defined_def null_fun_def) +lemma invalid_set_valid [simp,code_unfold]:"\(invalid::('\,'\::null) Set) = false" +by simp +lemma null_set_valid [simp,code_unfold]:"\(null::('\,'\::null) Set) = true" +apply(simp add: valid_def null_fun_def bot_fun_def bot_Set_0_def null_Set_0_def) +apply(subst Abs_Set_0_inject,simp_all add: null_option_def bot_option_def) +done + +text{* ... which means that we can have a type @{text "('\,('\,('\) Integer) Set) Set"} +corresponding exactly to Set(Set(Integer)) in OCL notation. Note that the parameter +@{text "'\"} still refers to the object universe; making the OCL semantics entirely parametric +in the object universe makes it possible to study (and prove) its properties +independently from a concrete class diagram. *} + +subsection{* Constants on Sets *} +definition mtSet::"('\,'\::null) Set" ("Set{}") +where "Set{} \ (\ \. Abs_Set_0 \\{}::'\ set\\ )" + + +lemma mtSet_defined[simp,code_unfold]:"\(Set{}) = true" +apply(rule ext, auto simp: mtSet_def defined_def null_Set_0_def + bot_Set_0_def bot_fun_def null_fun_def) +by(simp_all add: Abs_Set_0_inject bot_option_def null_Set_0_def null_option_def) + +lemma mtSet_valid[simp,code_unfold]:"\(Set{}) = true" +apply(rule ext,auto simp: mtSet_def valid_def null_Set_0_def + bot_Set_0_def bot_fun_def null_fun_def) +by(simp_all add: Abs_Set_0_inject bot_option_def null_Set_0_def null_option_def) + +lemma mtSet_rep_set: "\\Rep_Set_0 (Set{} \)\\ = {}" + apply(simp add: mtSet_def, subst Abs_Set_0_inverse) +by(simp add: bot_option_def)+ + +lemma [simp,code_unfold]: "const Set{}" +by(simp add: const_def mtSet_def) + + +text{* Note that the collection types in OCL allow for null to be included; + however, there is the null-collection into which inclusion yields invalid. *} + +section{* Complex Types: The Set-Collection Type (II) Library *} + +text{* This part provides a collection of operators for the Set type. *} + +subsection{* Computational Operations on Set *} + +subsubsection{* Definition *} + +definition OclIncluding :: "[('\,'\::null) Set,('\,'\) val] \ ('\,'\) Set" +where "OclIncluding x y = (\ \. if (\ x) \ = true \ \ (\ y) \ = true \ + then Abs_Set_0 \\ \\Rep_Set_0 (x \)\\ \ {y \} \\ + else \ )" +notation OclIncluding ("_->including'(_')") + +syntax + "_OclFinset" :: "args => ('\,'a::null) Set" ("Set{(_)}") +translations + "Set{x, xs}" == "CONST OclIncluding (Set{xs}) x" + "Set{x}" == "CONST OclIncluding (Set{}) x " + +definition OclExcluding :: "[('\,'\::null) Set,('\,'\) val] \ ('\,'\) Set" +where "OclExcluding x y = (\ \. if (\ x) \ = true \ \ (\ y) \ = true \ + then Abs_Set_0 \\ \\Rep_Set_0 (x \)\\ - {y \} \\ + else \ )" +notation OclExcluding ("_->excluding'(_')") + +definition OclIncludes :: "[('\,'\::null) Set,('\,'\) val] \ '\ Boolean" +where "OclIncludes x y = (\ \. if (\ x) \ = true \ \ (\ y) \ = true \ + then \\(y \) \ \\Rep_Set_0 (x \)\\ \\ + else \ )" +notation OclIncludes ("_->includes'(_')" (*[66,65]65*)) + +definition OclExcludes :: "[('\,'\::null) Set,('\,'\) val] \ '\ Boolean" +where "OclExcludes x y = (not(OclIncludes x y))" +notation OclExcludes ("_->excludes'(_')" (*[66,65]65*)) + +text{* The case of the size definition is somewhat special, we admit +explicitly in Featherweight OCL the possibility of infinite sets. For +the size definition, this requires an extra condition that assures +that the cardinality of the set is actually a defined integer. *} + +definition OclSize :: "('\,'\::null)Set \ '\ Integer" +where "OclSize x = (\ \. if (\ x) \ = true \ \ finite(\\Rep_Set_0 (x \)\\) + then \\ int(card \\Rep_Set_0 (x \)\\) \\ + else \ )" +notation (* standard ascii syntax *) + OclSize ("_->size'(')" (*[66]*)) + +text{* The following definition follows the requirement of the +standard to treat null as neutral element of sets. It is +a well-documented exception from the general strictness +rule and the rule that the distinguished argument self should +be non-null. *} +definition OclIsEmpty :: "('\,'\::null) Set \ '\ Boolean" +where "OclIsEmpty x = ((\ x and not (\ x)) or ((OclSize x) \ \))" +notation OclIsEmpty ("_->isEmpty'(')" (*[66]*)) + +definition OclNotEmpty :: "('\,'\::null) Set \ '\ Boolean" +where "OclNotEmpty x = not(OclIsEmpty x)" +notation OclNotEmpty ("_->notEmpty'(')" (*[66]*)) + +(* Slight breach of naming convention in order to avoid naming conflict on constant.*) +definition OclANY :: "[('\,'\::null) Set] \ ('\,'\) val" +where "OclANY x = (\ \. if (\ x) \ = true \ + then if (\ x and OclNotEmpty x) \ = true \ + then SOME y. y \ \\Rep_Set_0 (x \)\\ + else null \ + else \ )" +notation OclANY ("_->any'(')") +(* actually, this definition covers only: X->any(true) of the standard, which foresees +a (totally correct) high-level definition +source->any(iterator | body) = +source->select(iterator | body)->asSequence()->first(). Since we don't have sequences, +we have to go for a direct---restricted---definition. *) + + +text{* The definition of OclForall mimics the one of @{term "OclAnd"}: +OclForall is not a strict operation. *} +definition OclForall :: "[('\,'\::null)Set,('\,'\)val\('\)Boolean] \ '\ Boolean" +where "OclForall S P = (\ \. if (\ S) \ = true \ + then if (\x\\\Rep_Set_0 (S \)\\. P(\ _. x) \ = false \) + then false \ + else if (\x\\\Rep_Set_0 (S \)\\. P(\ _. x) \ = \ \) + then \ \ + else if (\x\\\Rep_Set_0 (S \)\\. P(\ _. x) \ = null \) + then null \ + else true \ + else \)" +syntax + "_OclForall" :: "[('\,'\::null) Set,id,('\)Boolean] \ '\ Boolean" ("(_)->forAll'(_|_')") +translations + "X->forAll(x | P)" == "CONST OclForall X (%x. P)" + +text{* Like OclForall, OclExists is also not strict. *} +definition OclExists :: "[('\,'\::null) Set,('\,'\)val\('\)Boolean] \ '\ Boolean" +where "OclExists S P = not(OclForall S (\ X. not (P X)))" + +syntax + "_OclExist" :: "[('\,'\::null) Set,id,('\)Boolean] \ '\ Boolean" ("(_)->exists'(_|_')") +translations + "X->exists(x | P)" == "CONST OclExists X (%x. P)" + +definition OclIterate :: "[('\,'\::null) Set,('\,'\::null)val, + ('\,'\)val\('\,'\)val\('\,'\)val] \ ('\,'\)val" +where "OclIterate S A F = (\ \. if (\ S) \ = true \ \ (\ A) \ = true \ \ finite\\Rep_Set_0 (S \)\\ + then (Finite_Set.fold (F) (A) ((\a \. a) ` \\Rep_Set_0 (S \)\\))\ + else \)" +syntax + "_OclIterate" :: "[('\,'\::null) Set, idt, idt, '\, '\] => ('\,'\)val" + ("_ ->iterate'(_;_=_ | _')" (*[71,100,70]50*)) +translations + "X->iterate(a; x = A | P)" == "CONST OclIterate X A (%a. (% x. P))" + +definition OclSelect :: "[('\,'\::null)Set,('\,'\)val\('\)Boolean] \ ('\,'\)Set" +where "OclSelect S P = (\\. if (\ S) \ = true \ + then if (\x\\\Rep_Set_0 (S \)\\. P(\ _. x) \ = \ \) + then \ + else Abs_Set_0 \\{x\\\ Rep_Set_0 (S \)\\. P (\_. x) \ \ false \}\\ + else \)" +syntax + "_OclSelect" :: "[('\,'\::null) Set,id,('\)Boolean] \ '\ Boolean" ("(_)->select'(_|_')") +translations + "X->select(x | P)" == "CONST OclSelect X (% x. P)" + +definition OclReject :: "[('\,'\::null)Set,('\,'\)val\('\)Boolean] \ ('\,'\::null)Set" +where "OclReject S P = OclSelect S (not o P)" +syntax + "_OclReject" :: "[('\,'\::null) Set,id,('\)Boolean] \ '\ Boolean" ("(_)->reject'(_|_')") +translations + "X->reject(x | P)" == "CONST OclReject X (% x. P)" + +subsubsection{* Definition (futur operators) *} + +consts (* abstract set collection operations *) + OclCount :: "[('\,'\::null) Set,('\,'\) Set] \ '\ Integer" + OclSum :: " ('\,'\::null) Set \ '\ Integer" + OclIncludesAll :: "[('\,'\::null) Set,('\,'\) Set] \ '\ Boolean" + OclExcludesAll :: "[('\,'\::null) Set,('\,'\) Set] \ '\ Boolean" + OclComplement :: " ('\,'\::null) Set \ ('\,'\) Set" + OclUnion :: "[('\,'\::null) Set,('\,'\) Set] \ ('\,'\) Set" + OclIntersection:: "[('\,'\::null) Set,('\,'\) Set] \ ('\,'\) Set" + +notation + OclCount ("_->count'(_')" (*[66,65]65*)) +notation + OclSum ("_->sum'(')" (*[66]*)) +notation + OclIncludesAll ("_->includesAll'(_')" (*[66,65]65*)) +notation + OclExcludesAll ("_->excludesAll'(_')" (*[66,65]65*)) +notation + OclComplement ("_->complement'(')") +notation + OclUnion ("_->union'(_')" (*[66,65]65*)) +notation + OclIntersection("_->intersection'(_')" (*[71,70]70*)) + +subsection{* Validity and Definedness Properties *} + +subsubsection{* OclIncluding *} + +lemma OclIncluding_defined_args_valid: +"(\ \ \(X->including(x))) = ((\ \(\ X)) \ (\ \(\ x)))" +proof - + have A : "\ \ {X. X = bot \ X = null \ (\x\\\X\\. x \ bot)}" by(simp add: bot_option_def) + have B : "\\\ \ {X. X = bot \ X = null \ (\x\\\X\\. x \ bot)}" + by(simp add: null_option_def bot_option_def) + have C : "(\ \(\ X)) \ (\ \(\ x)) \ + \\insert (x \) \\Rep_Set_0 (X \)\\\\ \ {X. X = bot \ X = null \ (\x\\\X\\. x \ bot)}" + by(frule Set_inv_lemma, simp add: foundation18 invalid_def) + have D: "(\ \ \(X->including(x))) \ ((\ \(\ X)) \ (\ \(\ x)))" + by(auto simp: OclIncluding_def OclValid_def true_def valid_def false_def StrongEq_def + defined_def invalid_def bot_fun_def null_fun_def + split: bool.split_asm HOL.split_if_asm option.split) + have E: "(\ \(\ X)) \ (\ \(\ x)) \ (\ \ \(X->including(x)))" + apply(subst OclIncluding_def, subst OclValid_def, subst defined_def) + apply(auto simp: OclValid_def null_Set_0_def bot_Set_0_def null_fun_def bot_fun_def) + apply(frule Abs_Set_0_inject[OF C A, simplified OclValid_def, THEN iffD1], + simp_all add: bot_option_def) + apply(frule Abs_Set_0_inject[OF C B, simplified OclValid_def, THEN iffD1], + simp_all add: bot_option_def) + done +show ?thesis by(auto dest:D intro:E) +qed + + + +lemma OclIncluding_valid_args_valid: +"(\ \ \(X->including(x))) = ((\ \(\ X)) \ (\ \(\ x)))" +proof - + have D: "(\ \ \(X->including(x))) \ ((\ \(\ X)) \ (\ \(\ x)))" + by(auto simp: OclIncluding_def OclValid_def true_def valid_def false_def StrongEq_def + defined_def invalid_def bot_fun_def null_fun_def + split: bool.split_asm HOL.split_if_asm option.split) + have E: "(\ \(\ X)) \ (\ \(\ x)) \ (\ \ \(X->including(x)))" + by(simp add: foundation20 OclIncluding_defined_args_valid) +show ?thesis by(auto dest:D intro:E) +qed + +lemma OclIncluding_defined_args_valid'[simp,code_unfold]: +"\(X->including(x)) = ((\ X) and (\ x))" +by(auto intro!: transform2_rev simp:OclIncluding_defined_args_valid foundation10 defined_and_I) + +lemma OclIncluding_valid_args_valid''[simp,code_unfold]: +"\(X->including(x)) = ((\ X) and (\ x))" +by(auto intro!: transform2_rev simp:OclIncluding_valid_args_valid foundation10 defined_and_I) + + +subsubsection{* OclExcluding *} + +lemma OclExcluding_defined_args_valid: +"(\ \ \(X->excluding(x))) = ((\ \(\ X)) \ (\ \(\ x)))" +proof - + have A : "\ \ {X. X = bot \ X = null \ (\x\\\X\\. x \ bot)}" by(simp add: bot_option_def) + have B : "\\\ \ {X. X = bot \ X = null \ (\x\\\X\\. x \ bot)}" + by(simp add: null_option_def bot_option_def) + have C : "(\ \(\ X)) \ (\ \(\ x)) \ + \\\\Rep_Set_0 (X \)\\ - {x \}\\ \ {X. X = bot \ X = null \ (\x\\\X\\. x \ bot)}" + by(frule Set_inv_lemma, simp add: foundation18 invalid_def) + have D: "(\ \ \(X->excluding(x))) \ ((\ \(\ X)) \ (\ \(\ x)))" + by(auto simp: OclExcluding_def OclValid_def true_def valid_def false_def StrongEq_def + defined_def invalid_def bot_fun_def null_fun_def + split: bool.split_asm HOL.split_if_asm option.split) + have E: "(\ \(\ X)) \ (\ \(\ x)) \ (\ \ \(X->excluding(x)))" + apply(subst OclExcluding_def, subst OclValid_def, subst defined_def) + apply(auto simp: OclValid_def null_Set_0_def bot_Set_0_def null_fun_def bot_fun_def) + apply(frule Abs_Set_0_inject[OF C A, simplified OclValid_def, THEN iffD1], + simp_all add: bot_option_def) + apply(frule Abs_Set_0_inject[OF C B, simplified OclValid_def, THEN iffD1], + simp_all add: bot_option_def) + done +show ?thesis by(auto dest:D intro:E) +qed + + +lemma OclExcluding_valid_args_valid: +"(\ \ \(X->excluding(x))) = ((\ \(\ X)) \ (\ \(\ x)))" +proof - + have D: "(\ \ \(X->excluding(x))) \ ((\ \(\ X)) \ (\ \(\ x)))" + by(auto simp: OclExcluding_def OclValid_def true_def valid_def false_def StrongEq_def + defined_def invalid_def bot_fun_def null_fun_def + split: bool.split_asm HOL.split_if_asm option.split) + have E: "(\ \(\ X)) \ (\ \(\ x)) \ (\ \ \(X->excluding(x)))" + by(simp add: foundation20 OclExcluding_defined_args_valid) +show ?thesis by(auto dest:D intro:E) +qed + + +lemma OclExcluding_valid_args_valid'[simp,code_unfold]: +"\(X->excluding(x)) = ((\ X) and (\ x))" +by(auto intro!: transform2_rev simp:OclExcluding_defined_args_valid foundation10 defined_and_I) + + +lemma OclExcluding_valid_args_valid''[simp,code_unfold]: +"\(X->excluding(x)) = ((\ X) and (\ x))" +by(auto intro!: transform2_rev simp:OclExcluding_valid_args_valid foundation10 defined_and_I) + +subsubsection{* OclIncludes *} + +lemma OclIncludes_defined_args_valid: +"(\ \ \(X->includes(x))) = ((\ \(\ X)) \ (\ \(\ x)))" +proof - + have A: "(\ \ \(X->includes(x))) \ ((\ \(\ X)) \ (\ \(\ x)))" + by(auto simp: OclIncludes_def OclValid_def true_def valid_def false_def StrongEq_def + defined_def invalid_def bot_fun_def null_fun_def + split: bool.split_asm HOL.split_if_asm option.split) + have B: "(\ \(\ X)) \ (\ \(\ x)) \ (\ \ \(X->includes(x)))" + by(auto simp: OclIncludes_def OclValid_def true_def false_def StrongEq_def + defined_def invalid_def valid_def bot_fun_def null_fun_def + bot_option_def null_option_def + split: bool.split_asm HOL.split_if_asm option.split) +show ?thesis by(auto dest:A intro:B) +qed + +lemma OclIncludes_valid_args_valid: +"(\ \ \(X->includes(x))) = ((\ \(\ X)) \ (\ \(\ x)))" +proof - + have A: "(\ \ \(X->includes(x))) \ ((\ \(\ X)) \ (\ \(\ x)))" + by(auto simp: OclIncludes_def OclValid_def true_def valid_def false_def StrongEq_def + defined_def invalid_def bot_fun_def null_fun_def + split: bool.split_asm HOL.split_if_asm option.split) + have B: "(\ \(\ X)) \ (\ \(\ x)) \ (\ \ \(X->includes(x)))" + by(auto simp: OclIncludes_def OclValid_def true_def false_def StrongEq_def + defined_def invalid_def valid_def bot_fun_def null_fun_def + bot_option_def null_option_def + split: bool.split_asm HOL.split_if_asm option.split) +show ?thesis by(auto dest:A intro:B) +qed + +lemma OclIncludes_valid_args_valid'[simp,code_unfold]: +"\(X->includes(x)) = ((\ X) and (\ x))" +by(auto intro!: transform2_rev simp:OclIncludes_defined_args_valid foundation10 defined_and_I) + +lemma OclIncludes_valid_args_valid''[simp,code_unfold]: +"\(X->includes(x)) = ((\ X) and (\ x))" +by(auto intro!: transform2_rev simp:OclIncludes_valid_args_valid foundation10 defined_and_I) + +subsubsection{* OclExcludes *} + +lemma OclExcludes_defined_args_valid: +"(\ \ \(X->excludes(x))) = ((\ \(\ X)) \ (\ \(\ x)))" +by (metis (hide_lams, no_types) + OclExcludes_def OclAnd_idem OclOr_def OclOr_idem defined_not_I OclIncludes_defined_args_valid) + +lemma OclExcludes_valid_args_valid: +"(\ \ \(X->excludes(x))) = ((\ \(\ X)) \ (\ \(\ x)))" +by (metis (hide_lams, no_types) + OclExcludes_def OclAnd_idem OclOr_def OclOr_idem valid_not_I OclIncludes_valid_args_valid) + +lemma OclExcludes_valid_args_valid'[simp,code_unfold]: +"\(X->excludes(x)) = ((\ X) and (\ x))" +by(auto intro!: transform2_rev simp:OclExcludes_defined_args_valid foundation10 defined_and_I) + +lemma OclExcludes_valid_args_valid''[simp,code_unfold]: +"\(X->excludes(x)) = ((\ X) and (\ x))" +by(auto intro!: transform2_rev simp:OclExcludes_valid_args_valid foundation10 defined_and_I) + +subsubsection{* OclSize *} + +lemma OclSize_defined_args_valid: "\ \ \ (X->size()) \ \ \ \ X" +by(auto simp: OclSize_def OclValid_def true_def valid_def false_def StrongEq_def + defined_def invalid_def bot_fun_def null_fun_def + split: bool.split_asm HOL.split_if_asm option.split) + +lemma OclSize_infinite: +assumes non_finite:"\ \ not(\(S->size()))" +shows "(\ \ not(\(S))) \ \ finite \\Rep_Set_0 (S \)\\" +apply(insert non_finite, simp) +apply(rule impI) +apply(simp add: OclSize_def OclValid_def defined_def) +apply(case_tac "finite \\Rep_Set_0 (S \)\\", + simp_all add:null_fun_def null_option_def bot_fun_def bot_option_def) +done + +lemma "\ \ \ X \ \ finite \\Rep_Set_0 (X \)\\ \ \ \ \ \ (X->size())" +by(simp add: OclSize_def OclValid_def defined_def bot_fun_def false_def true_def) + +lemma size_defined: + assumes X_finite: "\\. finite \\Rep_Set_0 (X \)\\" + shows "\ (X->size()) = \ X" + apply(rule ext, simp add: cp_defined[of "X->size()"] OclSize_def) + apply(simp add: defined_def bot_option_def bot_fun_def null_option_def null_fun_def X_finite) +done + +lemma size_defined': + assumes X_finite: "finite \\Rep_Set_0 (X \)\\" + shows "(\ \ \ (X->size())) = (\ \ \ X)" + apply(simp add: cp_defined[of "X->size()"] OclSize_def OclValid_def) + apply(simp add: defined_def bot_option_def bot_fun_def null_option_def null_fun_def X_finite) +done + +subsubsection{* OclIsEmpty *} + +lemma OclIsEmpty_defined_args_valid:"\ \ \ (X->isEmpty()) \ \ \ \ X" + apply(auto simp: OclIsEmpty_def OclValid_def defined_def valid_def false_def true_def + bot_fun_def null_fun_def OclAnd_def OclOr_def OclNot_def + split: split_if_asm) + apply(case_tac "(X->size() \ \) \", simp add: bot_option_def, simp, rename_tac x) + apply(case_tac x, simp add: null_option_def bot_option_def, simp) + apply(simp add: OclSize_def StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r valid_def) +by (metis (hide_lams, no_types) + OCL_core.bot_fun_def OclValid_def defined_def foundation2 invalid_def) + +lemma "\ \ \ (null->isEmpty())" +by(auto simp: OclIsEmpty_def OclValid_def defined_def valid_def false_def true_def + bot_fun_def null_fun_def OclAnd_def OclOr_def OclNot_def null_is_valid + split: split_if_asm) + +lemma OclIsEmpty_infinite: "\ \ \ X \ \ finite \\Rep_Set_0 (X \)\\ \ \ \ \ \ (X->isEmpty())" + apply(auto simp: OclIsEmpty_def OclValid_def defined_def valid_def false_def true_def + bot_fun_def null_fun_def OclAnd_def OclOr_def OclNot_def + split: split_if_asm) + apply(case_tac "(X->size() \ \) \", simp add: bot_option_def, simp, rename_tac x) + apply(case_tac x, simp add: null_option_def bot_option_def, simp) +by(simp add: OclSize_def StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r valid_def bot_fun_def false_def true_def invalid_def) + +subsubsection{* OclNotEmpty *} + +lemma OclNotEmpty_defined_args_valid:"\ \ \ (X->notEmpty()) \ \ \ \ X" +by (metis (hide_lams, no_types) OclNotEmpty_def OclNot_defargs OclNot_not foundation6 foundation9 + OclIsEmpty_defined_args_valid) + +lemma "\ \ \ (null->notEmpty())" +by (metis (hide_lams, no_types) OclNotEmpty_def OclAnd_false1 OclAnd_idem OclIsEmpty_def + OclNot3 OclNot4 OclOr_def defined2 defined4 transform1 valid2) + +lemma OclNotEmpty_infinite: "\ \ \ X \ \ finite \\Rep_Set_0 (X \)\\ \ \ \ \ \ (X->notEmpty())" + apply(simp add: OclNotEmpty_def) + apply(drule OclIsEmpty_infinite, simp) +by (metis OclNot_defargs OclNot_not foundation6 foundation9) + +lemma OclNotEmpty_has_elt : "\ \ \ X \ + \ \ X->notEmpty() \ + \e. e \ \\Rep_Set_0 (X \)\\" + apply(simp add: OclNotEmpty_def OclIsEmpty_def deMorgan1 deMorgan2, drule foundation5) + apply(subst (asm) (2) OclNot_def, + simp add: OclValid_def StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r StrongEq_def + split: split_if_asm) + prefer 2 + apply(simp add: invalid_def bot_option_def true_def) + apply(simp add: OclSize_def valid_def split: split_if_asm, + simp_all add: false_def true_def bot_option_def bot_fun_def OclInt0_def) +by (metis equals0I) + +subsubsection{* OclANY *} + +lemma OclANY_defined_args_valid: "\ \ \ (X->any()) \ \ \ \ X" +by(auto simp: OclANY_def OclValid_def true_def valid_def false_def StrongEq_def + defined_def invalid_def bot_fun_def null_fun_def OclAnd_def + split: bool.split_asm HOL.split_if_asm option.split) + +lemma "\ \ \ X \ \ \ X->isEmpty() \ \ \ \ \ (X->any())" + apply(simp add: OclANY_def OclValid_def) + apply(subst cp_defined, subst cp_OclAnd, simp add: OclNotEmpty_def, subst (1 2) cp_OclNot, + simp add: cp_OclNot[symmetric] cp_OclAnd[symmetric] cp_defined[symmetric], + simp add: false_def true_def) +by(drule foundation20[simplified OclValid_def true_def], simp) + +lemma OclANY_valid_args_valid: +"(\ \ \(X->any())) = (\ \ \ X)" +proof - + have A: "(\ \ \(X->any())) \ ((\ \(\ X)))" + by(auto simp: OclANY_def OclValid_def true_def valid_def false_def StrongEq_def + defined_def invalid_def bot_fun_def null_fun_def + split: bool.split_asm HOL.split_if_asm option.split) + have B: "(\ \(\ X)) \ (\ \ \(X->any()))" + apply(auto simp: OclANY_def OclValid_def true_def false_def StrongEq_def + defined_def invalid_def valid_def bot_fun_def null_fun_def + bot_option_def null_option_def null_is_valid + OclAnd_def + split: bool.split_asm HOL.split_if_asm option.split) + apply(frule Set_inv_lemma[OF foundation16[THEN iffD2], OF conjI], simp) + apply(subgoal_tac "(\ X) \ = true \") + prefer 2 + apply (metis (hide_lams, no_types) OclValid_def foundation16) + apply(simp add: true_def, + drule OclNotEmpty_has_elt[simplified OclValid_def true_def], simp) + by(erule exE, + insert someI2[where Q = "\x. x \ \" and P = "\y. y \ \\Rep_Set_0 (X \)\\"], + simp) + show ?thesis by(auto dest:A intro:B) +qed + +lemma OclANY_valid_args_valid''[simp,code_unfold]: +"\(X->any()) = (\ X)" +by(auto intro!: OclANY_valid_args_valid transform2_rev) + +(* and higher order ones : forall, exists, iterate, select, reject... *) + +subsection{* Execution with Invalid or Null or Infinite Set as Argument *} + + +subsubsection{* OclIncluding *} + +lemma OclIncluding_invalid[simp,code_unfold]:"(invalid->including(x)) = invalid" +by(simp add: bot_fun_def OclIncluding_def invalid_def defined_def valid_def false_def true_def) + +lemma OclIncluding_invalid_args[simp,code_unfold]:"(X->including(invalid)) = invalid" +by(simp add: OclIncluding_def invalid_def bot_fun_def defined_def valid_def false_def true_def) + +lemma OclIncluding_null[simp,code_unfold]:"(null->including(x)) = invalid" +by(simp add: OclIncluding_def invalid_def bot_fun_def defined_def valid_def false_def true_def) + + +subsubsection{* OclExcluding *} + +lemma OclExcluding_invalid[simp,code_unfold]:"(invalid->excluding(x)) = invalid" +by(simp add: bot_fun_def OclExcluding_def invalid_def defined_def valid_def false_def true_def) + +lemma OclExcluding_invalid_args[simp,code_unfold]:"(X->excluding(invalid)) = invalid" +by(simp add: OclExcluding_def invalid_def bot_fun_def defined_def valid_def false_def true_def) + +lemma OclExcluding_null[simp,code_unfold]:"(null->excluding(x)) = invalid" +by(simp add: OclExcluding_def invalid_def bot_fun_def defined_def valid_def false_def true_def) + +subsubsection{* OclIncludes *} + +lemma OclIncludes_invalid[simp,code_unfold]:"(invalid->includes(x)) = invalid" +by(simp add: bot_fun_def OclIncludes_def invalid_def defined_def valid_def false_def true_def) + +lemma OclIncludes_invalid_args[simp,code_unfold]:"(X->includes(invalid)) = invalid" +by(simp add: OclIncludes_def invalid_def bot_fun_def defined_def valid_def false_def true_def) + +lemma OclIncludes_null[simp,code_unfold]:"(null->includes(x)) = invalid" +by(simp add: OclIncludes_def invalid_def bot_fun_def defined_def valid_def false_def true_def) + +subsubsection{* OclExcludes *} + +lemma OclExcludes_invalid[simp,code_unfold]:"(invalid->excludes(x)) = invalid" +by(simp add: OclExcludes_def OclNot_def, simp add: invalid_def bot_option_def) + +lemma OclExcludes_invalid_args[simp,code_unfold]:"(X->excludes(invalid)) = invalid" +by(simp add: OclExcludes_def OclNot_def, simp add: invalid_def bot_option_def) + +lemma OclExcludes_null[simp,code_unfold]:"(null->excludes(x)) = invalid" +by(simp add: OclExcludes_def OclNot_def, simp add: invalid_def bot_option_def) + +subsubsection{* OclSize *} + +lemma OclSize_invalid[simp,code_unfold]:"(invalid->size()) = invalid" +by(simp add: bot_fun_def OclSize_def invalid_def defined_def valid_def false_def true_def) + +lemma OclSize_null[simp,code_unfold]:"(null->size()) = invalid" +by(rule ext, + simp add: bot_fun_def null_fun_def null_is_valid OclSize_def + invalid_def defined_def valid_def false_def true_def) + +subsubsection{* OclIsEmpty *} + +lemma OclIsEmpty_invalid[simp,code_unfold]:"(invalid->isEmpty()) = invalid" +by(simp add: OclIsEmpty_def) + +lemma OclIsEmpty_null[simp,code_unfold]:"(null->isEmpty()) = true" +by(simp add: OclIsEmpty_def) + +subsubsection{* OclNotEmpty *} + +lemma OclNotEmpty_invalid[simp,code_unfold]:"(invalid->notEmpty()) = invalid" +by(simp add: OclNotEmpty_def) + +lemma OclNotEmpty_null[simp,code_unfold]:"(null->notEmpty()) = false" +by(simp add: OclNotEmpty_def) + +subsubsection{* OclANY *} + +lemma OclANY_invalid[simp,code_unfold]:"(invalid->any()) = invalid" +by(simp add: bot_fun_def OclANY_def invalid_def defined_def valid_def false_def true_def) + +lemma OclANY_null[simp,code_unfold]:"(null->any()) = null" +by(simp add: OclANY_def false_def true_def) + +subsubsection{* OclForall *} + +lemma OclForall_invalid[simp,code_unfold]:"invalid->forAll(a| P a) = invalid" +by(simp add: bot_fun_def invalid_def OclForall_def defined_def valid_def false_def true_def) + +lemma OclForall_null[simp,code_unfold]:"null->forAll(a | P a) = invalid" +by(simp add: bot_fun_def invalid_def OclForall_def defined_def valid_def false_def true_def) + +subsubsection{* OclExists *} + +lemma OclExists_invalid[simp,code_unfold]:"invalid->exists(a| P a) = invalid" +by(simp add: OclExists_def) + +lemma OclExists_null[simp,code_unfold]:"null->exists(a | P a) = invalid" +by(simp add: OclExists_def) + +subsubsection{* OclIterate *} + +lemma OclIterate_invalid[simp,code_unfold]:"invalid->iterate(a; x = A | P a x) = invalid" +by(simp add: bot_fun_def invalid_def OclIterate_def defined_def valid_def false_def true_def) + +lemma OclIterate_null[simp,code_unfold]:"null->iterate(a; x = A | P a x) = invalid" +by(simp add: bot_fun_def invalid_def OclIterate_def defined_def valid_def false_def true_def) + + +lemma OclIterate_invalid_args[simp,code_unfold]:"S->iterate(a; x = invalid | P a x) = invalid" +by(simp add: bot_fun_def invalid_def OclIterate_def defined_def valid_def false_def true_def) + +text{* An open question is this ... *} +lemma (*OclIterate_null_args[simp,code_unfold]:*) "S->iterate(a; x = null | P a x) = invalid" +oops +(* In the definition above, this does not hold in general. + And I believe, this is how it should be ... *) + +lemma OclIterate_infinite: +assumes non_finite: "\ \ not(\(S->size()))" +shows "(OclIterate S A F) \ = invalid \" +apply(insert non_finite [THEN OclSize_infinite]) +apply(subst (asm) foundation9, simp) +by(metis OclIterate_def OclValid_def invalid_def) + +subsubsection{* OclSelect *} + +lemma OclSelect_invalid[simp,code_unfold]:"invalid->select(a | P a) = invalid" +by(simp add: bot_fun_def invalid_def OclSelect_def defined_def valid_def false_def true_def) + +lemma OclSelect_null[simp,code_unfold]:"null->select(a | P a) = invalid" +by(simp add: bot_fun_def invalid_def OclSelect_def defined_def valid_def false_def true_def) + +subsubsection{* OclReject *} + +lemma OclReject_invalid[simp,code_unfold]:"invalid->reject(a | P a) = invalid" +by(simp add: OclReject_def) + +lemma OclReject_null[simp,code_unfold]:"null->reject(a | P a) = invalid" +by(simp add: OclReject_def) + +subsection{* Context Passing *} + +lemma cp_OclIncluding: +"(X->including(x)) \ = ((\ _. X \)->including(\ _. x \)) \" +by(auto simp: OclIncluding_def StrongEq_def invalid_def + cp_defined[symmetric] cp_valid[symmetric]) + +lemma cp_OclExcluding: +"(X->excluding(x)) \ = ((\ _. X \)->excluding(\ _. x \)) \" +by(auto simp: OclExcluding_def StrongEq_def invalid_def + cp_defined[symmetric] cp_valid[symmetric]) + +lemma cp_OclIncludes: +"(X->includes(x)) \ = ((\ _. X \)->includes(\ _. x \)) \" +by(auto simp: OclIncludes_def StrongEq_def invalid_def + cp_defined[symmetric] cp_valid[symmetric]) + +lemma cp_OclIncludes1: +"(X->includes(x)) \ = (X->includes(\ _. x \)) \" +by(auto simp: OclIncludes_def StrongEq_def invalid_def + cp_defined[symmetric] cp_valid[symmetric]) + +lemma cp_OclExcludes: +"(X->excludes(x)) \ = ((\ _. X \)->excludes(\ _. x \)) \" +by(simp add: OclExcludes_def OclNot_def, subst cp_OclIncludes, simp) + +lemma cp_OclSize: "X->size() \ = ((\_. X \)->size()) \" +by(simp add: OclSize_def cp_defined[symmetric]) + +lemma cp_OclIsEmpty: "X->isEmpty() \ = ((\_. X \)->isEmpty()) \" + apply(simp only: OclIsEmpty_def) + apply(subst (2) cp_OclOr, + subst cp_OclAnd, + subst cp_OclNot, + subst cp_StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r) +by(simp add: cp_defined[symmetric] cp_valid[symmetric] cp_StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r[symmetric] + cp_OclSize[symmetric] cp_OclNot[symmetric] cp_OclAnd[symmetric] cp_OclOr[symmetric]) + +lemma cp_OclNotEmpty: "X->notEmpty() \ = ((\_. X \)->notEmpty()) \" + apply(simp only: OclNotEmpty_def) + apply(subst (2) cp_OclNot) +by(simp add: cp_OclNot[symmetric] cp_OclIsEmpty[symmetric]) + +lemma cp_OclANY: "X->any() \ = ((\_. X \)->any()) \" + apply(simp only: OclANY_def) + apply(subst (2) cp_OclAnd) +by(simp only: cp_OclAnd[symmetric] cp_defined[symmetric] cp_valid[symmetric] + cp_OclNotEmpty[symmetric]) + +lemma cp_OclForall: +"(S->forAll(x | P x)) \ = ((\ _. S \)->forAll(x | P (\ _. x \))) \" +by(simp add: OclForall_def cp_defined[symmetric]) + +(* first-order version !*) +lemma cp_OclForall1 [simp,intro!]: +"cp S \ cp (\X. ((S X)->forAll(x | P x)))" +apply(simp add: cp_def) +apply(erule exE, rule exI, intro allI) +apply(erule_tac x=X in allE) +by(subst cp_OclForall, simp) + +lemma (*cp_OclForall2 [simp,intro!]:*) +"cp (\X St x. P (\\. x) X St) \ cp S \ cp (\X. (S X)->forAll(x|P x X)) " +apply(simp only: cp_def) +oops + +lemma (*cp_OclForall:*) +"cp S \ + (\ x. cp(P x)) \ + cp(\X. ((S X)->forAll(x | P x X)))" +oops + +(* + +lemma cp_OclForall2 [simp,intro!]: +"\ cp (\ X St.(\x. P (\\. x) X St)); + cp (S :: (('a,'c)VAL \ ('a,('b::bot))Set)) \ + \ cp(\X. \ Y \ S X \ P (Y\'a \ 'b) X) " +apply(simp only: cp_def OclForAll_def) +apply(erule exE)+ +apply(rule exI, rule allI, rule allI) +apply (simp only:) +apply(rule_tac t = "(\x. P (\\. x) X \ )" and + s = "f (X \ ) \ " in subst) +prefer 2 +ML{* Unify.search_bound:=1000; *} +apply(rule refl) +ML{* Unify.search_bound:=20; *} +(* Miracle ! This works. Definitively a unification problem !!! *) +apply simp +done (* temporary solution. *) + (* TODO: improve !!! *) + +*) + +lemma cp_OclExists: +"(S->exists(x | P x)) \ = ((\ _. S \)->exists(x | P (\ _. x \))) \" +by(simp add: OclExists_def OclNot_def, subst cp_OclForall, simp) + +(* first-order version !*) +lemma cp_OclExists1 [simp,intro!]: +"cp S \ cp (\X. ((S X)->exists(x | P x)))" +apply(simp add: cp_def) +apply(erule exE, rule exI, intro allI) +apply(erule_tac x=X in allE) +by(subst cp_OclExists,simp) + +lemma cp_OclIterate: "(X->iterate(a; x = A | P a x)) \ = + ((\ _. X \)->iterate(a; x = A | P a x)) \" +by(simp add: OclIterate_def cp_defined[symmetric]) + +lemma cp_OclSelect: "(X->select(a | P a)) \ = + ((\ _. X \)->select(a | P a)) \" +by(simp add: OclSelect_def cp_defined[symmetric]) + +lemma cp_OclReject: "(X->reject(a | P a)) \ = + ((\ _. X \)->reject(a | P a)) \" +by(simp add: OclReject_def, subst cp_OclSelect, simp) + +lemmas cp_intro''[intro!,simp,code_unfold] = + cp_intro' + cp_OclIncluding [THEN allI[THEN allI[THEN allI[THEN cpI2]], of "OclIncluding"]] + cp_OclExcluding [THEN allI[THEN allI[THEN allI[THEN cpI2]], of "OclExcluding"]] + cp_OclIncludes [THEN allI[THEN allI[THEN allI[THEN cpI2]], of "OclIncludes"]] + cp_OclExcludes [THEN allI[THEN allI[THEN allI[THEN cpI2]], of "OclExcludes"]] + cp_OclSize [THEN allI[THEN allI[THEN cpI1], of "OclSize"]] + cp_OclIsEmpty [THEN allI[THEN allI[THEN cpI1], of "OclIsEmpty"]] + cp_OclNotEmpty [THEN allI[THEN allI[THEN cpI1], of "OclNotEmpty"]] + cp_OclANY [THEN allI[THEN allI[THEN cpI1], of "OclANY"]] + +subsection{* Const *} + +lemma const_OclIncluding[simp,code_unfold] : + assumes const_x : "const x" + and const_S : "const S" + shows "const (S->including(x))" + proof - + have A:"\\ \'. \ (\ \ \ x) \ (S->including(x) \) = (S->including(x) \')" + apply(simp add: foundation18) + apply(erule const_subst[OF const_x const_invalid],simp_all) + by(rule const_charn[OF const_invalid]) + have B: "\ \ \'. \ (\ \ \ S) \ (S->including(x) \) = (S->including(x) \')" + apply(simp add: foundation16', elim disjE) + apply(erule const_subst[OF const_S const_invalid],simp_all) + apply(rule const_charn[OF const_invalid]) + apply(erule const_subst[OF const_S const_null],simp_all) + by(rule const_charn[OF const_invalid]) + show ?thesis + apply(simp only: const_def,intro allI, rename_tac \ \') + apply(case_tac "\ (\ \ \ x)", simp add: A) + apply(case_tac "\ (\ \ \ S)", simp_all add: B) + apply(frule_tac \'1= \' in const_OclValid2[OF const_x, THEN iffD1]) + apply(frule_tac \'1= \' in const_OclValid1[OF const_S, THEN iffD1]) + apply(simp add: OclIncluding_def OclValid_def) + apply(subst const_charn[OF const_x]) + apply(subst const_charn[OF const_S]) + by simp +qed + +section{* Fundamental Predicates on Set: Strict Equality *} + +subsection{* Definition *} + +text{* After the part of foundational operations on sets, we detail here equality on sets. +Strong equality is inherited from the OCL core, but we have to consider +the case of the strict equality. We decide to overload strict equality in the +same way we do for other value's in OCL:*} + +defs StrictRefEq\<^sub>S\<^sub>e\<^sub>t : + "(x::('\,'\::null)Set) \ y \ \ \. if (\ x) \ = true \ \ (\ y) \ = true \ + then (x \ y)\ + else invalid \" + +text{* One might object here that for the case of objects, this is an empty definition. +The answer is no, we will restrain later on states and objects such that any object +has its oid stored inside the object (so the ref, under which an object can be referenced +in the store will represented in the object itself). For such well-formed stores that satisfy +this invariant (the WFF-invariant), the referential equality and the +strong equality---and therefore the strict equality on sets in the sense above---coincides.*} + +subsection{* Logic and Algebraic Layer on Set *} + +subsubsection{* Reflexivity *} + +text{* To become operational, we derive: *} + +lemma StrictRefEq\<^sub>S\<^sub>e\<^sub>t_refl[simp,code_unfold]: +"((x::('\,'\::null)Set) \ x) = (if (\ x) then true else invalid endif)" +by(rule ext, simp add: StrictRefEq\<^sub>S\<^sub>e\<^sub>t OclIf_def) + +subsubsection{* Symmetry *} + +lemma StrictRefEq\<^sub>S\<^sub>e\<^sub>t_sym: +"((x::('\,'\::null)Set) \ y) = (y \ x)" +by(simp add: StrictRefEq\<^sub>S\<^sub>e\<^sub>t, subst StrongEq_sym, rule ext, simp) + +subsubsection{* Execution with Invalid or Null as Argument *} + +lemma StrictRefEq\<^sub>S\<^sub>e\<^sub>t_strict1[simp,code_unfold]: "((x::('\,'\::null)Set) \ invalid)= invalid" +by(simp add:StrictRefEq\<^sub>S\<^sub>e\<^sub>t false_def true_def) + +lemma StrictRefEq\<^sub>S\<^sub>e\<^sub>t_strict2[simp,code_unfold]: "(invalid \ (y::('\,'\::null)Set))= invalid" +by(simp add:StrictRefEq\<^sub>S\<^sub>e\<^sub>t false_def true_def) + +lemma StrictRefEq\<^sub>S\<^sub>e\<^sub>t_strictEq_valid_args_valid: +"(\ \ \ ((x::('\,'\::null)Set) \ y)) = ((\ \ (\ x)) \ (\ \ \ y))" +proof - + have A: "\ \ \ (x \ y) \ \ \ \ x \ \ \ \ y" + apply(simp add: StrictRefEq\<^sub>S\<^sub>e\<^sub>t valid_def OclValid_def defined_def) + apply(simp add: invalid_def bot_fun_def split: split_if_asm) + done + have B: "(\ \ \ x) \ (\ \ \ y) \ \ \ \ (x \ y)" + apply(simp add: StrictRefEq\<^sub>S\<^sub>e\<^sub>t, elim conjE) + apply(drule foundation13[THEN iffD2],drule foundation13[THEN iffD2]) + apply(rule cp_validity[THEN iffD2]) + apply(subst cp_defined, simp add: foundation22) + apply(simp add: cp_defined[symmetric] cp_validity[symmetric]) + done + show ?thesis by(auto intro!: A B) +qed + +subsubsection{* Behavior vs StrongEq *} + +lemma StrictRefEq\<^sub>S\<^sub>e\<^sub>t_vs_StrongEq: +"\ \ \ x \ \ \ \ y \ (\ \ (((x::('\,'\::null)Set) \ y) \ (x \ y)))" +apply(drule foundation13[THEN iffD2],drule foundation13[THEN iffD2]) +by(simp add:StrictRefEq\<^sub>S\<^sub>e\<^sub>t foundation22) + +subsubsection{* Context Passing *} + + +lemma cp_StrictRefEq\<^sub>S\<^sub>e\<^sub>t:"((X::('\,'\::null)Set) \ Y) \ = ((\_. X \) \ (\_. Y \)) \" +by(simp add:StrictRefEq\<^sub>S\<^sub>e\<^sub>t cp_StrongEq[symmetric] cp_valid[symmetric]) + + +subsubsection{* Const *} + +lemma const_StrictRefEq\<^sub>S\<^sub>e\<^sub>t : + assumes "const (X :: (_,_::null) Set)" + assumes "const X'" + shows "const (X \ X')" + apply(simp only: const_def, intro allI) + proof - + fix \1 \2 show "(X \ X') \1 = (X \ X') \2" + apply(simp only: StrictRefEq\<^sub>S\<^sub>e\<^sub>t) + by(simp add: const_valid[OF assms(1), simplified const_def, THEN spec, THEN spec, of \1 \2] + const_valid[OF assms(2), simplified const_def, THEN spec, THEN spec, of \1 \2] + const_true[simplified const_def, THEN spec, THEN spec, of \1 \2] + const_invalid[simplified const_def, THEN spec, THEN spec, of \1 \2] + const_StrongEq[OF assms, simplified const_def, THEN spec, THEN spec]) +qed + + +section{* Execution on Set's Operators (with mtSet and recursive case as arguments) *} + +subsection{* OclIncluding *} + +lemma OclIncluding_finite_rep_set : + assumes X_def : "\ \ \ X" + and x_val : "\ \ \ x" + shows "finite \\Rep_Set_0 (X->including(x) \)\\ = finite \\Rep_Set_0 (X \)\\" + proof - + have C : "\\insert (x \) \\Rep_Set_0 (X \)\\\\ \ {X. X = bot \ X = null \ (\x\\\X\\. x \ bot)}" + by(insert X_def x_val, frule Set_inv_lemma, simp add: foundation18 invalid_def) + show "?thesis" + by(insert X_def x_val, + auto simp: OclIncluding_def Abs_Set_0_inverse[OF C] + dest: foundation13[THEN iffD2, THEN foundation22[THEN iffD1]]) +qed + +lemma OclIncluding_rep_set: + assumes S_def: "\ \ \ S" + shows "\\Rep_Set_0 (S->including(\_. \\x\\) \)\\ = insert \\x\\ \\Rep_Set_0 (S \)\\" + apply(simp add: OclIncluding_def S_def[simplified OclValid_def]) + apply(subst Abs_Set_0_inverse, simp add: bot_option_def null_option_def) + apply(insert Set_inv_lemma[OF S_def], metis bot_option_def not_Some_eq) +by(simp) + +lemma OclIncluding_notempty_rep_set: +assumes X_def: "\ \ \ X" + and a_val: "\ \ \ a" + shows "\\Rep_Set_0 (X->including(a) \)\\ \ {}" + apply(simp add: OclIncluding_def X_def[simplified OclValid_def] a_val[simplified OclValid_def]) + apply(subst Abs_Set_0_inverse, simp add: bot_option_def null_option_def) + apply(insert Set_inv_lemma[OF X_def], metis a_val foundation18') +by(simp) + +lemma OclIncluding_includes: + assumes "\ \ X->includes(x)" + shows "X->including(x) \ = X \" +proof - + have includes_def: "\ \ X->includes(x) \ \ \ \ X" + by (metis OCL_core.bot_fun_def OclIncludes_def OclValid_def defined3 foundation16) + + have includes_val: "\ \ X->includes(x) \ \ \ \ x" + by (metis (hide_lams, no_types) foundation6 + OclIncludes_valid_args_valid' OclIncluding_valid_args_valid OclIncluding_valid_args_valid'') + + show ?thesis + apply(insert includes_def[OF assms] includes_val[OF assms] assms, + simp add: OclIncluding_def OclIncludes_def OclValid_def true_def) + apply(drule insert_absorb, simp, subst abs_rep_simp') + by(simp_all add: OclValid_def true_def) +qed + + +subsection{* OclExcluding *} + +lemma OclExcluding_charn0[simp]: +assumes val_x:"\ \ (\ x)" +shows "\ \ ((Set{}->excluding(x)) \ Set{})" +proof - + have A : "\None\ \ {X. X = bot \ X = null \ (\x\\\X\\. x \ bot)}" + by(simp add: null_option_def bot_option_def) + have B : "\\{}\\ \ {X. X = bot \ X = null \ (\x\\\X\\. x \ bot)}" by(simp add: mtSet_def) + + show ?thesis using val_x + apply(auto simp: OclValid_def OclIncludes_def OclNot_def false_def true_def StrongEq_def + OclExcluding_def mtSet_def defined_def bot_fun_def null_fun_def null_Set_0_def) + apply(auto simp: mtSet_def OCL_lib.Set_0.Abs_Set_0_inverse + OCL_lib.Set_0.Abs_Set_0_inject[OF B A]) + done +qed + + +lemma OclExcluding_charn0_exec[simp,code_unfold]: +"(Set{}->excluding(x)) = (if (\ x) then Set{} else invalid endif)" +proof - + have A: "\ \. (Set{}->excluding(invalid)) \ = (if (\ invalid) then Set{} else invalid endif) \" + by simp + have B: "\ \ x. \ \ (\ x) \ + (Set{}->excluding(x)) \ = (if (\ x) then Set{} else invalid endif) \" + by(simp add: OclExcluding_charn0[THEN foundation22[THEN iffD1]]) + show ?thesis + apply(rule ext, rename_tac \) + apply(case_tac "\ \ (\ x)") + apply(simp add: B) + apply(simp add: foundation18) + apply(subst cp_OclExcluding, simp) + apply(simp add: cp_OclIf[symmetric] cp_OclExcluding[symmetric] cp_valid[symmetric] A) + done +qed + +lemma OclExcluding_charn1: +assumes def_X:"\ \ (\ X)" +and val_x:"\ \ (\ x)" +and val_y:"\ \ (\ y)" +and neq :"\ \ not(x \ y)" +shows "\ \ ((X->including(x))->excluding(y)) \ ((X->excluding(y))->including(x))" +proof - + have C : "\\insert (x \) \\Rep_Set_0 (X \)\\\\ \ {X. X = bot \ X = null \ (\x\\\X\\. x \ bot)}" + by(insert def_X val_x, frule Set_inv_lemma, simp add: foundation18 invalid_def) + have D : "\\\\Rep_Set_0 (X \)\\ - {y \}\\ \ {X. X = bot \ X = null \ (\x\\\X\\. x \ bot)}" + by(insert def_X val_x, frule Set_inv_lemma, simp add: foundation18 invalid_def) + have E : "x \ \ y \" + by(insert neq, + auto simp: OclValid_def bot_fun_def OclIncluding_def OclIncludes_def + false_def true_def defined_def valid_def bot_Set_0_def + null_fun_def null_Set_0_def StrongEq_def OclNot_def) + + have G1 : "Abs_Set_0 \\insert (x \) \\Rep_Set_0 (X \)\\\\ \ Abs_Set_0 None" + by(insert C, simp add: Abs_Set_0_inject bot_option_def null_option_def) + have G2 : "Abs_Set_0 \\insert (x \) \\Rep_Set_0 (X \)\\\\ \ Abs_Set_0 \None\" + by(insert C, simp add: Abs_Set_0_inject bot_option_def null_option_def) + have G : "(\ (\_. Abs_Set_0 \\insert (x \) \\Rep_Set_0 (X \)\\\\)) \ = true \" + by(auto simp: OclValid_def false_def true_def defined_def + bot_fun_def bot_Set_0_def null_fun_def null_Set_0_def G1 G2) + + have H1 : "Abs_Set_0 \\\\Rep_Set_0 (X \)\\ - {y \}\\ \ Abs_Set_0 None" + by(insert D, simp add: Abs_Set_0_inject bot_option_def null_option_def) + have H2 : "Abs_Set_0 \\\\Rep_Set_0 (X \)\\ - {y \}\\ \ Abs_Set_0 \None\" + by(insert D, simp add: Abs_Set_0_inject bot_option_def null_option_def) + have H : "(\ (\_. Abs_Set_0 \\\\Rep_Set_0 (X \)\\ - {y \}\\)) \ = true \" + by(auto simp: OclValid_def false_def true_def defined_def + bot_fun_def bot_Set_0_def null_fun_def null_Set_0_def H1 H2) + + have Z : "insert (x \) \\Rep_Set_0 (X \)\\ - {y \} = insert (x \) (\\Rep_Set_0 (X \)\\ - {y \})" + by(auto simp: E) + show ?thesis + apply(insert def_X[THEN foundation13[THEN iffD2]] val_x[THEN foundation13[THEN iffD2]] + val_y[THEN foundation13[THEN iffD2]]) + apply(simp add: foundation22 OclIncluding_def OclExcluding_def def_X[THEN foundation17]) + apply(subst cp_defined, simp)+ + apply(simp add: G H Abs_Set_0_inverse[OF C] Abs_Set_0_inverse[OF D] Z) + done +qed + +lemma OclExcluding_charn2: +assumes def_X:"\ \ (\ X)" +and val_x:"\ \ (\ x)" +shows "\ \ (((X->including(x))->excluding(x)) \ (X->excluding(x)))" +proof - + have C : "\\insert (x \) \\Rep_Set_0 (X \)\\\\ \ {X. X = bot \ X = null \ (\x\\\X\\. x \ bot)}" + by(insert def_X val_x, frule Set_inv_lemma, simp add: foundation18 invalid_def) + have G1 : "Abs_Set_0 \\insert (x \) \\Rep_Set_0 (X \)\\\\ \ Abs_Set_0 None" + by(insert C, simp add: Abs_Set_0_inject bot_option_def null_option_def) + have G2 : "Abs_Set_0 \\insert (x \) \\Rep_Set_0 (X \)\\\\ \ Abs_Set_0 \None\" + by(insert C, simp add: Abs_Set_0_inject bot_option_def null_option_def) + show ?thesis + apply(insert def_X[THEN foundation17] val_x[THEN foundation19]) + apply(auto simp: OclValid_def bot_fun_def OclIncluding_def OclIncludes_def false_def true_def + invalid_def defined_def valid_def bot_Set_0_def null_fun_def null_Set_0_def + StrongEq_def) + apply(subst cp_OclExcluding) + apply(auto simp:OclExcluding_def) + apply(simp add: Abs_Set_0_inverse[OF C]) + apply(simp_all add: false_def true_def defined_def valid_def + null_fun_def bot_fun_def null_Set_0_def bot_Set_0_def + split: bool.split_asm HOL.split_if_asm option.split) + apply(auto simp: G1 G2) + done +qed + +text{* One would like a generic theorem of the form: +\begin{isar}[mathescape] +lemma OclExcluding_charn_exec: + "(X->including(x::('$\mathfrak{A}$,'a::null)val)->excluding(y)) = + (if \ X then if x \ y + then X->excluding(y) + else X->excluding(y)->including(x) + endif + else invalid endif)" +\end{isar} +Unfortunately, this does not hold in general, since referential equality is +an overloaded concept and has to be defined for each type individually. +Consequently, it is only valid for concrete type instances for Boolean, +Integer, and Sets thereof... +*} + + +text{* The computational law \emph{OclExcluding-charn-exec} becomes generic since it +uses strict equality which in itself is generic. It is possible to prove +the following generic theorem and instantiate it later (using properties +that link the polymorphic logical strong equality with the concrete instance +of strict quality).*} +lemma OclExcluding_charn_exec: + assumes strict1: "(x \ invalid) = invalid" + and strict2: "(invalid \ y) = invalid" + and StrictRefEq_valid_args_valid: "\ (x::('\,'a::null)val) y \. + (\ \ \ (x \ y)) = ((\ \ (\ x)) \ (\ \ \ y))" + and cp_StrictRefEq: "\ (X::('\,'a::null)val) Y \. (X \ Y) \ = ((\_. X \) \ (\_. Y \)) \" + and StrictRefEq_vs_StrongEq: "\ (x::('\,'a::null)val) y \. + \ \ \ x \ \ \ \ y \ (\ \ ((x \ y) \ (x \ y)))" + shows "(X->including(x::('\,'a::null)val)->excluding(y)) = + (if \ X then if x \ y + then X->excluding(y) + else X->excluding(y)->including(x) + endif + else invalid endif)" +proof - + (* Lifting theorems, largely analogous OclIncludes_execute_generic, + with the same problems wrt. strict equality. *) + have A1: "\\. \ \ (X \ invalid) \ + (X->including(x)->includes(y)) \ = invalid \" + apply(rule foundation22[THEN iffD1]) + by(erule StrongEq_L_subst2_rev, simp,simp) + + have B1: "\\. \ \ (X \ null) \ + (X->including(x)->includes(y)) \ = invalid \" + apply(rule foundation22[THEN iffD1]) + by(erule StrongEq_L_subst2_rev, simp,simp) + + have A2: "\\. \ \ (X \ invalid) \ X->including(x)->excluding(y) \ = invalid \" + apply(rule foundation22[THEN iffD1]) + by(erule StrongEq_L_subst2_rev, simp,simp) + + have B2: "\\. \ \ (X \ null) \ X->including(x)->excluding(y) \ = invalid \" + apply(rule foundation22[THEN iffD1]) + by(erule StrongEq_L_subst2_rev, simp,simp) + + note [simp] = cp_StrictRefEq [THEN allI[THEN allI[THEN allI[THEN cpI2]], of "StrictRefEq"]] + + have C: "\\. \ \ (x \ invalid) \ + (X->including(x)->excluding(y)) \ = + (if x \ y then X->excluding(y) else X->excluding(y)->including(x) endif) \" + apply(rule foundation22[THEN iffD1]) + apply(erule StrongEq_L_subst2_rev,simp,simp) + by(simp add: strict2) + + have D: "\\. \ \ (y \ invalid) \ + (X->including(x)->excluding(y)) \ = + (if x \ y then X->excluding(y) else X->excluding(y)->including(x) endif) \" + apply(rule foundation22[THEN iffD1]) + apply(erule StrongEq_L_subst2_rev,simp,simp) + by (simp add: strict1) + + have E: "\\. \ \ \ x \ \ \ \ y \ + (if x \ y then X->excluding(y) else X->excluding(y)->including(x) endif) \ = + (if x \ y then X->excluding(y) else X->excluding(y)->including(x) endif) \" + apply(subst cp_OclIf) + apply(subst StrictRefEq_vs_StrongEq[THEN foundation22[THEN iffD1]]) + by(simp_all add: cp_OclIf[symmetric]) + + have F: "\\. \ \ \ X \ \ \ \ x \ \ \ (x \ y) \ + (X->including(x)->excluding(y) \) = (X->excluding(y) \)" + apply(drule StrongEq_L_sym) + apply(rule foundation22[THEN iffD1]) + apply(erule StrongEq_L_subst2_rev,simp) + by(simp add: OclExcluding_charn2) + + show ?thesis + apply(rule ext, rename_tac "\") + apply(case_tac "\ (\ \ (\ X))", simp add:def_split_local,elim disjE A1 B1 A2 B2) + apply(case_tac "\ (\ \ (\ x))", + simp add:foundation18 foundation22[symmetric], + drule StrongEq_L_sym) + apply(simp add: foundation22 C) + apply(case_tac "\ (\ \ (\ y))", + simp add:foundation18 foundation22[symmetric], + drule StrongEq_L_sym, simp add: foundation22 D, simp) + apply(subst E,simp_all) + apply(case_tac "\ \ not (x \ y)") + apply(simp add: OclExcluding_charn1[simplified foundation22] + OclExcluding_charn2[simplified foundation22]) + apply(simp add: foundation9 F) + done +qed + +(* Hack to work around OF-Bug *) +schematic_lemma OclExcluding_charn_exec\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r[simp,code_unfold]: "?X" +by(rule OclExcluding_charn_exec[OF StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_strict1 StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_strict2 + StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_defined_args_valid + cp_StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_vs_StrongEq], simp_all) + +schematic_lemma OclExcluding_charn_exec\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n[simp,code_unfold]: "?X" +by(rule OclExcluding_charn_exec[OF StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n_strict1 StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n_strict2 + StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n_defined_args_valid + cp_StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n_vs_StrongEq], simp_all) + +schematic_lemma OclExcluding_charn_exec\<^sub>S\<^sub>e\<^sub>t[simp,code_unfold]: "?X" +by(rule OclExcluding_charn_exec[OF StrictRefEq\<^sub>S\<^sub>e\<^sub>t_strict1 StrictRefEq\<^sub>S\<^sub>e\<^sub>t_strict2 + StrictRefEq\<^sub>S\<^sub>e\<^sub>t_strictEq_valid_args_valid + cp_StrictRefEq\<^sub>S\<^sub>e\<^sub>t StrictRefEq\<^sub>S\<^sub>e\<^sub>t_vs_StrongEq], simp_all) + + +lemma OclExcluding_finite_rep_set : + assumes X_def : "\ \ \ X" + and x_val : "\ \ \ x" + shows "finite \\Rep_Set_0 (X->excluding(x) \)\\ = finite \\Rep_Set_0 (X \)\\" + proof - + have C : "\\\\Rep_Set_0 (X \)\\ - {x \}\\ \ {X. X = bot \ X = null \ (\x\\\X\\. x \ bot)}" + apply(insert X_def x_val, frule Set_inv_lemma) + apply(simp add: foundation18 invalid_def) + done + show "?thesis" + by(insert X_def x_val, + auto simp: OclExcluding_def Abs_Set_0_inverse[OF C] + dest: foundation13[THEN iffD2, THEN foundation22[THEN iffD1]]) +qed + +lemma OclExcluding_rep_set: + assumes S_def: "\ \ \ S" + shows "\\Rep_Set_0 (S->excluding(\_. \\x\\) \)\\ = \\Rep_Set_0 (S \)\\ - {\\x\\}" + apply(simp add: OclExcluding_def S_def[simplified OclValid_def]) + apply(subst Abs_Set_0_inverse, simp add: bot_option_def null_option_def) + apply(insert Set_inv_lemma[OF S_def], metis Diff_iff bot_option_def not_None_eq) +by(simp) + +subsection{* OclIncludes *} + + +lemma OclIncludes_charn0[simp]: +assumes val_x:"\ \ (\ x)" +shows "\ \ not(Set{}->includes(x))" +using val_x +apply(auto simp: OclValid_def OclIncludes_def OclNot_def false_def true_def) +apply(auto simp: mtSet_def OCL_lib.Set_0.Abs_Set_0_inverse) +done + + +lemma OclIncludes_charn0'[simp,code_unfold]: +"Set{}->includes(x) = (if \ x then false else invalid endif)" +proof - + have A: "\ \. (Set{}->includes(invalid)) \ = (if (\ invalid) then false else invalid endif) \" + by simp + have B: "\ \ x. \ \ (\ x) \ (Set{}->includes(x)) \ = (if \ x then false else invalid endif) \" + apply(frule OclIncludes_charn0, simp add: OclValid_def) + apply(rule foundation21[THEN fun_cong, simplified StrongEq_def,simplified, + THEN iffD1, of _ _ "false"]) + by simp + show ?thesis + apply(rule ext, rename_tac \) + apply(case_tac "\ \ (\ x)") + apply(simp_all add: B foundation18) + apply(subst cp_OclIncludes, simp add: cp_OclIncludes[symmetric] A) + done +qed + +(*declare [[names_long,show_types,show_sorts]]*) +lemma OclIncludes_charn1: +assumes def_X:"\ \ (\ X)" +assumes val_x:"\ \ (\ x)" +shows "\ \ (X->including(x)->includes(x))" +proof - + have C : "\\insert (x \) \\Rep_Set_0 (X \)\\\\ \ {X. X = bot \ X = null \ (\x\\\X\\. x \ bot)}" + by(insert def_X val_x, frule Set_inv_lemma, simp add: foundation18 invalid_def) + show ?thesis + apply(subst OclIncludes_def, simp add: foundation10[simplified OclValid_def] OclValid_def + def_X[simplified OclValid_def] val_x[simplified OclValid_def]) + apply(simp add: OclIncluding_def def_X[simplified OclValid_def] val_x[simplified OclValid_def] + Abs_Set_0_inverse[OF C] true_def) + done +qed + + + +lemma OclIncludes_charn2: +assumes def_X:"\ \ (\ X)" +and val_x:"\ \ (\ x)" +and val_y:"\ \ (\ y)" +and neq :"\ \ not(x \ y)" +shows "\ \ (X->including(x)->includes(y)) \ (X->includes(y))" +proof - + have C : "\\insert (x \) \\Rep_Set_0 (X \)\\\\ \ {X. X = bot \ X = null \ (\x\\\X\\. x \ bot)}" + by(insert def_X val_x, frule Set_inv_lemma, simp add: foundation18 invalid_def) + show ?thesis + apply(subst OclIncludes_def, + simp add: def_X[simplified OclValid_def] val_x[simplified OclValid_def] + val_y[simplified OclValid_def] foundation10[simplified OclValid_def] + OclValid_def StrongEq_def) + apply(simp add: OclIncluding_def OclIncludes_def def_X[simplified OclValid_def] + val_x[simplified OclValid_def] val_y[simplified OclValid_def] + Abs_Set_0_inverse[OF C] true_def) + by(metis foundation22 foundation6 foundation9 neq) +qed + +text{* Here is again a generic theorem similar as above. *} + +lemma OclIncludes_execute_generic: +assumes strict1: "(x \ invalid) = invalid" +and strict2: "(invalid \ y) = invalid" +and cp_StrictRefEq: "\ (X::('\,'a::null)val) Y \. (X \ Y) \ = ((\_. X \) \ (\_. Y \)) \" +and StrictRefEq_vs_StrongEq: "\ (x::('\,'a::null)val) y \. + \ \ \ x \ \ \ \ y \ (\ \ ((x \ y) \ (x \ y)))" +shows + "(X->including(x::('\,'a::null)val)->includes(y)) = + (if \ X then if x \ y then true else X->includes(y) endif else invalid endif)" +proof - + have A: "\\. \ \ (X \ invalid) \ + (X->including(x)->includes(y)) \ = invalid \" + apply(rule foundation22[THEN iffD1]) + by(erule StrongEq_L_subst2_rev,simp,simp) + have B: "\\. \ \ (X \ null) \ + (X->including(x)->includes(y)) \ = invalid \" + apply(rule foundation22[THEN iffD1]) + by(erule StrongEq_L_subst2_rev,simp,simp) + + note [simp] = cp_StrictRefEq [THEN allI[THEN allI[THEN allI[THEN cpI2]], of "StrictRefEq"]] + + have C: "\\. \ \ (x \ invalid) \ + (X->including(x)->includes(y)) \ = + (if x \ y then true else X->includes(y) endif) \" + apply(rule foundation22[THEN iffD1]) + apply(erule StrongEq_L_subst2_rev,simp,simp) + by (simp add: strict2) + have D:"\\. \ \ (y \ invalid) \ + (X->including(x)->includes(y)) \ = + (if x \ y then true else X->includes(y) endif) \" + apply(rule foundation22[THEN iffD1]) + apply(erule StrongEq_L_subst2_rev,simp,simp) + by (simp add: strict1) + have E: "\\. \ \ \ x \ \ \ \ y \ + (if x \ y then true else X->includes(y) endif) \ = + (if x \ y then true else X->includes(y) endif) \" + apply(subst cp_OclIf) + apply(subst StrictRefEq_vs_StrongEq[THEN foundation22[THEN iffD1]]) + by(simp_all add: cp_OclIf[symmetric]) + have F: "\\. \ \ (x \ y) \ + (X->including(x)->includes(y)) \ = (X->including(x)->includes(x)) \" + apply(rule foundation22[THEN iffD1]) + by(erule StrongEq_L_subst2_rev,simp, simp) + show ?thesis + apply(rule ext, rename_tac "\") + apply(case_tac "\ (\ \ (\ X))", simp add:def_split_local,elim disjE A B) + apply(case_tac "\ (\ \ (\ x))", + simp add:foundation18 foundation22[symmetric], + drule StrongEq_L_sym) + apply(simp add: foundation22 C) + apply(case_tac "\ (\ \ (\ y))", + simp add:foundation18 foundation22[symmetric], + drule StrongEq_L_sym, simp add: foundation22 D, simp) + apply(subst E,simp_all) + apply(case_tac "\ \ not(x \ y)") + apply(simp add: OclIncludes_charn2[simplified foundation22]) + apply(simp add: foundation9 F + OclIncludes_charn1[THEN foundation13[THEN iffD2], + THEN foundation22[THEN iffD1]]) + done +qed + + +(* Hack to work around OF-Bug *) +schematic_lemma OclIncludes_execute\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r[simp,code_unfold]: "?X" +by(rule OclIncludes_execute_generic[OF StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_strict1 StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_strict2 + cp_StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r + StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_vs_StrongEq], simp_all) + + +schematic_lemma OclIncludes_execute\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n[simp,code_unfold]: "?X" +by(rule OclIncludes_execute_generic[OF StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n_strict1 StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n_strict2 + cp_StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n + StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n_vs_StrongEq], simp_all) + + +schematic_lemma OclIncludes_execute\<^sub>S\<^sub>e\<^sub>t[simp,code_unfold]: "?X" +by(rule OclIncludes_execute_generic[OF StrictRefEq\<^sub>S\<^sub>e\<^sub>t_strict1 StrictRefEq\<^sub>S\<^sub>e\<^sub>t_strict2 + cp_StrictRefEq\<^sub>S\<^sub>e\<^sub>t + StrictRefEq\<^sub>S\<^sub>e\<^sub>t_vs_StrongEq], simp_all) + +lemma OclIncludes_including_generic : + assumes OclIncludes_execute_generic [simp] : "\X x y. + (X->including(x::('\,'a::null)val)->includes(y)) = + (if \ X then if x \ y then true else X->includes(y) endif else invalid endif)" + and StrictRefEq_strict'' : "\x y. \ ((x::('\,'a::null)val) \ y) = (\(x) and \(y))" + and a_val : "\ \ \ a" + and x_val : "\ \ \ x" + and S_incl : "\ \ (S)->includes((x::('\,'a::null)val))" + shows "\ \ S->including((a::('\,'a::null)val))->includes(x)" +proof - + have discr_eq_bot1_true : "\\. (\ \ = true \) = False" + by (metis OCL_core.bot_fun_def foundation1 foundation18' valid3) + have discr_eq_bot2_true : "\\. (\ = true \) = False" + by (metis bot_fun_def discr_eq_bot1_true) + have discr_neq_invalid_true : "\\. (invalid \ \ true \) = True" + by (metis discr_eq_bot2_true invalid_def) + have discr_eq_invalid_true : "\\. (invalid \ = true \) = False" + by (metis bot_option_def invalid_def option.simps(2) true_def) +show ?thesis + apply(simp) + apply(subgoal_tac "\ \ \ S") + prefer 2 + apply(insert S_incl[simplified OclIncludes_def], simp add: OclValid_def) + apply(metis discr_eq_bot2_true) + apply(simp add: cp_OclIf[of "\ S"] OclValid_def OclIf_def x_val[simplified OclValid_def] + discr_neq_invalid_true discr_eq_invalid_true) + by (metis OclValid_def S_incl StrictRefEq_strict'' a_val foundation10 foundation6 x_val) +qed + +lemmas OclIncludes_including\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r = + OclIncludes_including_generic[OF OclIncludes_execute\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_strict''] + +subsection{* OclExcludes *} + +subsection{* OclSize *} + +lemma [simp,code_unfold]: "Set{} ->size() = \" + apply(rule ext) + apply(simp add: defined_def mtSet_def OclSize_def + bot_Set_0_def bot_fun_def + null_Set_0_def null_fun_def) + apply(subst Abs_Set_0_inject, simp_all add: bot_option_def null_option_def) + +by(simp add: Abs_Set_0_inverse bot_option_def null_option_def OclInt0_def) + +lemma OclSize_including_exec[simp,code_unfold]: + "((X ->including(x)) ->size()) = (if \ X and \ x then + X ->size() `+ if X ->includes(x) then \ else \ endif + else + invalid + endif)" +proof - + + have valid_inject_true : "\\ P. (\ P) \ \ true \ \ (\ P) \ = false \" + apply(simp add: valid_def true_def false_def bot_fun_def bot_option_def + null_fun_def null_option_def) + by (case_tac "P \ = \", simp_all add: true_def) + have defined_inject_true : "\\ P. (\ P) \ \ true \ \ (\ P) \ = false \" + apply(simp add: defined_def true_def false_def bot_fun_def bot_option_def + null_fun_def null_option_def) + by (case_tac " P \ = \ \ P \ = null", simp_all add: true_def) + + show ?thesis + apply(rule ext, rename_tac \) + proof - + fix \ + have includes_notin: "\ \ \ X->includes(x) \ (\ X) \ = true \ \ (\ x) \ = true \ \ + x \ \ \\Rep_Set_0 (X \)\\" + by(simp add: OclIncludes_def OclValid_def true_def) + + have includes_def: "\ \ X->includes(x) \ \ \ \ X" + by (metis OCL_core.bot_fun_def OclIncludes_def OclValid_def defined3 foundation16) + + have includes_val: "\ \ X->includes(x) \ \ \ \ x" + by (metis (hide_lams, no_types) foundation6 + OclIncludes_valid_args_valid' OclIncluding_valid_args_valid OclIncluding_valid_args_valid'') + + have ins_in_Set_0: "\ \ \ X \ \ \ \ x \ + \\insert (x \) \\Rep_Set_0 (X \)\\\\ \ {X. X = \ \ X = null \ (\x\\\X\\. x \ \)}" + apply(simp add: bot_option_def null_option_def) + by (metis (hide_lams, no_types) Set_inv_lemma foundation18' foundation5) + + show "X->including(x)->size() \ = (if \ X and \ x + then X->size() `+ if X->includes(x) then \ else \ endif + else invalid endif) \" + apply(case_tac "\ \ \ X and \ x", simp) + apply(subst cp_OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r) + apply(case_tac "\ \ X->includes(x)", simp add: cp_OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r[symmetric]) + apply(case_tac "\ \ ((\ (X->size())) and not (\ (X->size())))", simp) + apply(drule foundation5[where P = "\ X->size()"], erule conjE) + apply(drule OclSize_infinite) + apply(frule includes_def, drule includes_val, simp) + apply(subst OclSize_def, subst OclIncluding_finite_rep_set, assumption+) + apply (metis (hide_lams, no_types) invalid_def) + + apply(subst OclIf_false', + metis (hide_lams, no_types) defined5 defined6 defined_and_I defined_not_I + foundation1 foundation9) + apply(subst cp_OclSize, simp add: OclIncluding_includes cp_OclSize[symmetric]) + (* *) + apply(subst OclIf_false', subst foundation9, + metis (hide_lams, no_types) OclIncludes_valid_args_valid', simp, simp add: OclSize_def) + apply(drule foundation5) + apply(subst (1 2) OclIncluding_finite_rep_set, fast+) + apply(subst (1 2) cp_OclAnd, subst (1 2) cp_OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r, simp) + apply(rule conjI) + apply(simp add: OclIncluding_def) + apply(subst Abs_Set_0_inverse[OF ins_in_Set_0], fast+) + apply(subst (asm) (2 3) OclValid_def, simp add: OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_def OclInt1_def) + apply(rule impI) + apply(drule Finite_Set.card.insert[where x = "x \"]) + apply(rule includes_notin, simp, simp) + apply (metis Suc_eq_plus1 int_1 of_nat_add) + + + apply(subst (1 2) OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_strict2[simplified invalid_def], simp) + apply(subst OclIncluding_finite_rep_set, fast+, simp add: OclValid_def) + (* *) + apply(subst OclIf_false', metis (hide_lams, no_types) defined6 foundation1 foundation9 + OclExcluding_valid_args_valid'') + by (metis cp_OclSize foundation18' OclIncluding_valid_args_valid'' invalid_def OclSize_invalid) + qed +qed + +subsection{* OclIsEmpty *} + +lemma [simp,code_unfold]: "Set{}->isEmpty() = true" +by(simp add: OclIsEmpty_def) + +lemma OclIsEmpty_including [simp]: +assumes X_def: "\ \ \ X" + and X_finite: "finite \\Rep_Set_0 (X \)\\" + and a_val: "\ \ \ a" +shows "X->including(a)->isEmpty() \ = false \" +proof - + have A1 : "\\ X. X \ = true \ \ X \ = false \ \ (X and not X) \ = false \" + by (metis (no_types) OclAnd_false1 OclAnd_idem OclImplies_def OclNot3 OclNot_not OclOr_false1 + cp_OclAnd cp_OclNot deMorgan1 deMorgan2) + + have defined_inject_true : "\\ P. (\ P) \ \ true \ \ (\ P) \ = false \" + apply(simp add: defined_def true_def false_def bot_fun_def bot_option_def + null_fun_def null_option_def) + by (case_tac " P \ = \ \ P \ = null", simp_all add: true_def) + + have B : "\X \. \ \ \ X \ X \ \ \ \ \ (X \ \) \ = false \" + by (metis OclAnd_true2 OclValid_def Sem_def foundation16 foundation22 valid4 + StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_strict' StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_strict'' + StrongEq_sym bool_split invalid_def null_fun_def null_non_OclInt0) + + show ?thesis + apply(simp add: OclIsEmpty_def del: OclSize_including_exec) + apply(subst cp_OclOr, subst A1) + apply(metis (hide_lams, no_types) defined_inject_true OclExcluding_valid_args_valid') + apply(simp add: cp_OclOr[symmetric] del: OclSize_including_exec) + apply(rule B, + rule foundation20, + metis (hide_lams, no_types) OclIncluding_defined_args_valid OclIncluding_finite_rep_set + X_def X_finite a_val size_defined') + apply(simp add: OclSize_def OclIncluding_finite_rep_set[OF X_def a_val] X_finite OclInt0_def) + by (metis OclValid_def X_def a_val foundation10 foundation6 + OclIncluding_notempty_rep_set[OF X_def a_val]) +qed + +subsection{* OclNotEmpty *} + +lemma [simp,code_unfold]: "Set{}->notEmpty() = false" +by(simp add: OclNotEmpty_def) + +lemma OclNotEmpty_including [simp,code_unfold]: +assumes X_def: "\ \ \ X" + and X_finite: "finite \\Rep_Set_0 (X \)\\" + and a_val: "\ \ \ a" +shows "X->including(a)->notEmpty() \ = true \" + apply(simp add: OclNotEmpty_def) + apply(subst cp_OclNot, subst OclIsEmpty_including, simp_all add: assms) +by (metis OclNot4 cp_OclNot) + +subsection{* OclANY *} + +lemma [simp,code_unfold]: "Set{}->any() = null" +by(rule ext, simp add: OclANY_def, simp add: false_def true_def) + +lemma OclANY_singleton_exec[simp,code_unfold]: + "(Set{}->including(a))->any() = a" + apply(rule ext, rename_tac \, simp add: mtSet_def OclANY_def) + apply(case_tac "\ \ \ a") + apply(simp add: OclValid_def mtSet_defined[simplified mtSet_def] + mtSet_valid[simplified mtSet_def] mtSet_rep_set[simplified mtSet_def]) + apply(subst (1 2) cp_OclAnd, + subst (1 2) OclNotEmpty_including[where X = "Set{}", simplified mtSet_def]) + apply(simp add: mtSet_defined[simplified mtSet_def]) + apply(metis (hide_lams, no_types) finite.emptyI mtSet_def mtSet_rep_set) + apply(simp add: OclValid_def) + apply(simp add: OclIncluding_def) + apply(rule conjI) + apply(subst (1 2) Abs_Set_0_inverse, simp add: bot_option_def null_option_def) + apply(simp, metis OclValid_def foundation18') + apply(simp) + apply(simp add: mtSet_defined[simplified mtSet_def]) + (* *) + apply(subgoal_tac "a \ = \") + prefer 2 + apply(simp add: OclValid_def valid_def bot_fun_def split: split_if_asm) + apply(simp) + apply(subst (1 2 3 4) cp_OclAnd, + simp add: mtSet_defined[simplified mtSet_def] valid_def bot_fun_def) +by(simp add: cp_OclAnd[symmetric], rule impI, simp add: false_def true_def) + +subsection{* OclForall *} + +lemma OclForall_mtSet_exec[simp,code_unfold] : +"((Set{})->forAll(z| P(z))) = true" +apply(simp add: OclForall_def) +apply(subst mtSet_def)+ +apply(subst Abs_Set_0_inverse, simp_all add: true_def)+ +done + +lemma OclForall_including_exec[simp,code_unfold] : + assumes cp0 : "cp P" + shows "((S->including(x))->forAll(z | P(z))) = (if \ S and \ x + then P x and (S->forAll(z | P(z))) + else invalid + endif)" +proof - + have cp: "\\. P x \ = P (\_. x \) \" + by(insert cp0, auto simp: cp_def) + + have insert_in_Set_0 : "\\. (\ \(\ S)) \ (\ \(\ x)) \ + \\insert (x \) \\Rep_Set_0 (S \)\\\\ \ {X. X = bot \ X = null \ (\x\\\X\\. x \ bot)}" + by(frule Set_inv_lemma, simp add: foundation18 invalid_def) + + have forall_including_invert : "\\ f. (f x \ = f (\ _. x \) \) \ + \ \ (\ S and \ x) \ + (\x\\\Rep_Set_0 (S->including(x) \)\\. f (\_. x) \) = + (f x \ \ (\x\\\Rep_Set_0 (S \)\\. f (\_. x) \))" + apply(drule foundation5, simp add: OclIncluding_def) + apply(subst Abs_Set_0_inverse) + apply(rule insert_in_Set_0, fast+) + by(simp add: OclValid_def) + + have exists_including_invert : "\\ f. (f x \ = f (\ _. x \) \) \ + \ \ (\ S and \ x) \ + (\x\\\Rep_Set_0 (S->including(x) \)\\. f (\_. x) \) = + (f x \ \ (\x\\\Rep_Set_0 (S \)\\. f (\_. x) \))" + apply(subst arg_cong[where f = "\x. \x", + OF forall_including_invert[where f = "\x \. \ (f x \)"], + simplified]) + by simp_all + + have cp_eq : "\\ v. (P x \ = v) = (P (\_. x \) \ = v)" by(subst cp, simp) + have cp_OclNot_eq : "\\ v. (P x \ \ v) = (P (\_. x \) \ \ v)" by(subst cp, simp) + + have foundation10': "\\ x y. (\ \ x) \ (\ \ y) \ \ \ (x and y)" + apply(erule conjE, subst foundation10) + by((rule foundation6)?, simp)+ + + have contradict_Rep_Set_0: "\\ S f. + \x\\\Rep_Set_0 S\\. f (\_. x) \ \ + (\x\\\Rep_Set_0 S\\. \ (f (\_. x) \)) = False" + by(case_tac "(\x\\\Rep_Set_0 S\\. \ (f (\_. x) \)) = True", simp_all) + + show ?thesis + apply(rule ext, rename_tac \) + apply(simp add: OclIf_def) + apply(simp add: cp_defined[of "\ S and \ x"] cp_defined[THEN sym]) + apply(intro conjI impI) + + apply(subgoal_tac "\ \ \ S") + prefer 2 + apply(drule foundation5[simplified OclValid_def], erule conjE)+ apply(simp add: OclValid_def) + + apply(subst OclForall_def) + apply(simp add: cp_OclAnd[THEN sym] OclValid_def + foundation10'[where x = "\ S" and y = "\ x", simplified OclValid_def]) + + apply(subgoal_tac "\ \ (\ S and \ x)") + prefer 2 + apply(simp add: OclValid_def) + + (* false *) + (* false YES *) + apply(case_tac "\x\\\Rep_Set_0 (S->including(x) \)\\. P (\_. x) \ = false \", simp_all) + apply(subst contradict_Rep_Set_0[where f = "\ x \. P x \ = false \"], simp)+ + apply(simp add: exists_including_invert[where f = "\ x \. P x \ = false \", OF cp_eq]) + + apply(simp add: cp_OclAnd[of "P x"]) + apply(erule disjE) + apply(simp only: cp_OclAnd[symmetric], simp) + + apply(subgoal_tac "OclForall S P \ = false \") + apply(simp only: cp_OclAnd[symmetric], simp) + apply(simp add: OclForall_def) + + (* false NO *) + apply(simp add: forall_including_invert[where f = "\ x \. P x \ \ false \", OF cp_OclNot_eq], + erule conjE) + + (* bot *) + (* bot YES *) + apply(case_tac "\x\\\Rep_Set_0 (S->including(x) \)\\. P (\_. x) \ = bot \", simp_all) + apply(subst contradict_Rep_Set_0[where f = "\ x \. P x \ = bot \"], simp)+ + apply(simp add: exists_including_invert[where f = "\ x \. P x \ = bot \", OF cp_eq]) + + apply(simp add: cp_OclAnd[of "P x"]) + apply(erule disjE) + + apply(subgoal_tac "OclForall S P \ \ false \") + apply(simp only: cp_OclAnd[symmetric], simp) + apply(simp add: OclForall_def true_def false_def + null_fun_def null_option_def bot_fun_def bot_option_def) + + apply(subgoal_tac "OclForall S P \ = bot \") + apply(simp only: cp_OclAnd[symmetric], simp) + apply(simp add: OclForall_def true_def false_def + null_fun_def null_option_def bot_fun_def bot_option_def) + + (* bot NO *) + apply(simp add: forall_including_invert[where f = "\ x \. P x \ \ bot \", OF cp_OclNot_eq], + erule conjE) + + (* null *) + (* null YES *) + apply(case_tac "\x\\\Rep_Set_0 (S->including(x) \)\\. P (\_. x) \ = null \", simp_all) + apply(subst contradict_Rep_Set_0[where f = "\ x \. P x \ = null \"], simp)+ + apply(simp add: exists_including_invert[where f = "\ x \. P x \ = null \", OF cp_eq]) + + apply(simp add: cp_OclAnd[of "P x"]) + apply(erule disjE) + + apply(subgoal_tac "OclForall S P \ \ false \ \ OclForall S P \ \ bot \") + apply(simp only: cp_OclAnd[symmetric], simp) + apply(simp add: OclForall_def true_def false_def + null_fun_def null_option_def bot_fun_def bot_option_def) + + apply(subgoal_tac "OclForall S P \ = null \") + apply(simp only: cp_OclAnd[symmetric], simp) + apply(simp add: OclForall_def true_def false_def + null_fun_def null_option_def bot_fun_def bot_option_def) + + (* null NO *) + apply(simp add: forall_including_invert[where f = "\ x \. P x \ \ null \", OF cp_OclNot_eq], + erule conjE) + + (* true *) + apply(simp add: cp_OclAnd[of "P x"] OclForall_def) + apply(subgoal_tac "P x \ = true \", simp) + apply(metis bot_fun_def bool_split foundation18' foundation2 valid1) + + (* invalid *) + by(metis OclForall_def OclIncluding_defined_args_valid' invalid_def) +qed + +subsection{* OclExists *} + +lemma OclExists_mtSet_exec[simp,code_unfold] : +"((Set{})->exists(z | P(z))) = false" +by(simp add: OclExists_def) + +lemma OclExists_including_exec[simp,code_unfold] : + assumes cp: "cp P" + shows "((S->including(x))->exists(z | P(z))) = (if \ S and \ x + then P x or (S->exists(z | P(z))) + else invalid + endif)" + by(simp add: OclExists_def OclOr_def OclForall_including_exec cp OclNot_inject) + + +subsection{* OclIterate *} + +lemma OclIterate_empty[simp,code_unfold]: "((Set{})->iterate(a; x = A | P a x)) = A" +proof - + have C : "\ \. (\ (\\. Abs_Set_0 \\{}\\)) \ = true \" + by (metis (no_types) defined_def mtSet_def mtSet_defined null_fun_def) + show ?thesis + apply(simp add: OclIterate_def mtSet_def Abs_Set_0_inverse valid_def C) + apply(rule ext, rename_tac \) + apply(case_tac "A \ = \ \", simp_all, simp add:true_def false_def bot_fun_def) + apply(simp add: Abs_Set_0_inverse) + done +qed + +text{* In particular, this does hold for A = null. *} + +lemma OclIterate_including: +assumes S_finite: "\ \ \(S->size())" +and F_valid_arg: "(\ A) \ = (\ (F a A)) \" +and F_commute: "comp_fun_commute F" +and F_cp: "\ x y \. F x y \ = F (\ _. x \) y \" +shows "((S->including(a))->iterate(a; x = A | F a x)) \ = + ((S->excluding(a))->iterate(a; x = F a A | F a x)) \" +proof - + have insert_in_Set_0 : "\\. (\ \(\ S)) \ (\ \(\ a)) \ + \\insert (a \) \\Rep_Set_0 (S \)\\\\ \ {X. X = bot \ X = null \ (\x\\\X\\. x \ bot)}" + by(frule Set_inv_lemma, simp add: foundation18 invalid_def) + + have insert_defined : "\\. (\ \(\ S)) \ (\ \(\ a)) \ + (\ (\_. Abs_Set_0 \\insert (a \) \\Rep_Set_0 (S \)\\\\)) \ = true \" + apply(subst defined_def) + apply(simp add: bot_Set_0_def bot_fun_def null_Set_0_def null_fun_def) + by(subst Abs_Set_0_inject, + rule insert_in_Set_0, simp_all add: null_option_def bot_option_def)+ + + have remove_finite : "finite \\Rep_Set_0 (S \)\\ \ + finite ((\a \. a) ` (\\Rep_Set_0 (S \)\\ - {a \}))" + by(simp) + + have remove_in_Set_0 : "\\. (\ \(\ S)) \ (\ \(\ a)) \ + \\\\Rep_Set_0 (S \)\\ - {a \}\\ \ {X. X = bot \ X = null \ (\x\\\X\\. x \ bot)}" + by(frule Set_inv_lemma, simp add: foundation18 invalid_def) + + have remove_defined : "\\. (\ \(\ S)) \ (\ \(\ a)) \ + (\ (\_. Abs_Set_0 \\\\Rep_Set_0 (S \)\\ - {a \}\\)) \ = true \" + apply(subst defined_def) + apply(simp add: bot_Set_0_def bot_fun_def null_Set_0_def null_fun_def) + by(subst Abs_Set_0_inject, + rule remove_in_Set_0, simp_all add: null_option_def bot_option_def)+ + + have abs_rep: "\x. \\x\\ \ {X. X = bot \ X = null \ (\x\\\X\\. x \ bot)} \ + \\Rep_Set_0 (Abs_Set_0 \\x\\)\\ = x" + by(subst Abs_Set_0_inverse, simp_all) + + have inject : "inj (\a \. a)" + by(rule inj_fun, simp) + + show ?thesis + apply(subst (1 2) cp_OclIterate, subst OclIncluding_def, subst OclExcluding_def) + apply(case_tac "\ ((\ S) \ = true \ \ (\ a) \ = true \)", simp) + + apply(subgoal_tac "OclIterate (\_. \) A F \ = OclIterate (\_. \) (F a A) F \", simp) + apply(rule conjI, blast+) + apply(simp add: OclIterate_def defined_def bot_option_def bot_fun_def false_def true_def) + + apply(simp add: OclIterate_def) + apply((subst abs_rep[OF insert_in_Set_0[simplified OclValid_def], of \], simp_all)+, + (subst abs_rep[OF remove_in_Set_0[simplified OclValid_def], of \], simp_all)+, + (subst insert_defined, simp_all add: OclValid_def)+, + (subst remove_defined, simp_all add: OclValid_def)+) + + apply(case_tac "\ ((\ A) \ = true \)", (simp add: F_valid_arg)+) + apply(rule impI, + subst Finite_Set.comp_fun_commute.fold_fun_left_comm[symmetric, OF F_commute], + rule remove_finite, simp) + + apply(subst image_set_diff[OF inject], simp) + apply(subgoal_tac "Finite_Set.fold F A (insert (\\'. a \) ((\a \. a) ` \\Rep_Set_0 (S \)\\)) \ = + F (\\'. a \) (Finite_Set.fold F A ((\a \. a) ` \\Rep_Set_0 (S \)\\ - {\\'. a \})) \") + apply(subst F_cp, simp) + + by(subst Finite_Set.comp_fun_commute.fold_insert_remove[OF F_commute], simp+) +qed + +subsection{* OclSelect *} + +lemma OclSelect_mtSet_exec[simp,code_unfold]: "OclSelect mtSet P = mtSet" + apply(rule ext, rename_tac \) + apply(simp add: OclSelect_def mtSet_def defined_def false_def true_def + bot_Set_0_def bot_fun_def null_Set_0_def null_fun_def) +by(( subst (1 2 3 4 5) Abs_Set_0_inverse + | subst Abs_Set_0_inject), (simp add: null_option_def bot_option_def)+)+ + +definition "OclSelect_body :: _ \ _ \ _ \ ('\, 'a option option) Set + \ (\P x acc. if P x \ false then acc else acc->including(x) endif)" + +lemma OclSelect_including_exec[simp,code_unfold]: + assumes P_cp : "cp P" + shows "OclSelect (X->including(y)) P = OclSelect_body P y (OclSelect (X->excluding(y)) P)" + (is "_ = ?select") +proof - + have P_cp: "\x \. P x \ = P (\_. x \) \" + by(insert P_cp, auto simp: cp_def) + + have ex_including : "\f X y \. \ \ \ X \ \ \ \ y \ + (\x\\\Rep_Set_0 (X->including(y) \)\\. f (P (\_. x)) \) = + (f (P (\_. y \)) \ \ (\x\\\Rep_Set_0 (X \)\\. f (P (\_. x)) \))" + apply(simp add: OclIncluding_def OclValid_def) + apply(subst Abs_Set_0_inverse, simp, (rule disjI2)+) + apply (metis (hide_lams, no_types) OclValid_def Set_inv_lemma foundation18') + by(simp) + have al_including : "\f X y \. \ \ \ X \ \ \ \ y \ + (\x\\\Rep_Set_0 (X->including(y) \)\\. f (P (\_. x)) \) = + (f (P (\_. y \)) \ \ (\x\\\Rep_Set_0 (X \)\\. f (P (\_. x)) \))" + apply(simp add: OclIncluding_def OclValid_def) + apply(subst Abs_Set_0_inverse, simp, (rule disjI2)+) + apply (metis (hide_lams, no_types) OclValid_def Set_inv_lemma foundation18') + by(simp) + have ex_excluding1 : "\f X y \. \ \ \ X \ \ \ \ y \ \ (f (P (\_. y \)) \) \ + (\x\\\Rep_Set_0 (X \)\\. f (P (\_. x)) \) = + (\x\\\Rep_Set_0 (X->excluding(y) \)\\. f (P (\_. x)) \)" + apply(simp add: OclExcluding_def OclValid_def) + apply(subst Abs_Set_0_inverse, simp, (rule disjI2)+) + apply (metis (no_types) Diff_iff OclValid_def Set_inv_lemma) + by(auto) + have al_excluding1 : "\f X y \. \ \ \ X \ \ \ \ y \ f (P (\_. y \)) \ \ + (\x\\\Rep_Set_0 (X \)\\. f (P (\_. x)) \) = + (\x\\\Rep_Set_0 (X->excluding(y) \)\\. f (P (\_. x)) \)" + apply(simp add: OclExcluding_def OclValid_def) + apply(subst Abs_Set_0_inverse, simp, (rule disjI2)+) + apply (metis (no_types) Diff_iff OclValid_def Set_inv_lemma) + by(auto) + have in_including : "\f X y \. \ \ \ X \ \ \ \ y \ + {x \ \\Rep_Set_0 (X->including(y) \)\\. f (P (\_. x) \)} = + (let s = {x \ \\Rep_Set_0 (X \)\\. f (P (\_. x) \)} in + if f (P (\_. y \) \) then insert (y \) s else s)" + apply(simp add: OclIncluding_def OclValid_def) + apply(subst Abs_Set_0_inverse, simp, (rule disjI2)+) + apply (metis (hide_lams, no_types) OclValid_def Set_inv_lemma foundation18') + by(simp add: Let_def, auto) + + let ?OclSet = "\S. \\S\\ \ {X. X = \ \ X = null \ (\x\\\X\\. x \ \)}" + have diff_in_Set_0 : "\\. (\ X) \ = true \ \ + ?OclSet (\\Rep_Set_0 (X \)\\ - {y \})" + apply(simp, (rule disjI2)+) + by (metis (mono_tags) Diff_iff OclValid_def Set_inv_lemma) + have ins_in_Set_0 : "\\. (\ X) \ = true \ \ (\ y) \ = true \ \ + ?OclSet (insert (y \) {x \ \\Rep_Set_0 (X \)\\. P (\_. x) \ \ false \})" + apply(simp, (rule disjI2)+) + by (metis (hide_lams, no_types) OclValid_def Set_inv_lemma foundation18') + have ins_in_Set_0' : "\\. (\ X) \ = true \ \ (\ y) \ = true \ \ + ?OclSet (insert (y \) {x \ \\Rep_Set_0 (X \)\\. x \ y \ \ P (\_. x) \ \ false \})" + apply(simp, (rule disjI2)+) + by (metis (hide_lams, no_types) OclValid_def Set_inv_lemma foundation18') + have ins_in_Set_0'' : "\\. (\ X) \ = true \ \ + ?OclSet {x \ \\Rep_Set_0 (X \)\\. P (\_. x) \ \ false \}" + apply(simp, (rule disjI2)+) + by (metis (hide_lams, no_types) OclValid_def Set_inv_lemma foundation18') + have ins_in_Set_0''' : "\\. (\ X) \ = true \ \ + ?OclSet {x \ \\Rep_Set_0 (X \)\\. x \ y \ \ P (\_. x) \ \ false \}" + apply(simp, (rule disjI2)+) + by (metis (hide_lams, no_types) OclValid_def Set_inv_lemma foundation18') + + have if_same : "\a b c d \. \ \ \ a \ b \ = d \ \ c \ = d \ \ + (if a then b else c endif) \ = d \" + by(simp add: OclIf_def OclValid_def) + + have invert_including : "\P y \. P \ = \ \ P->including(y) \ = \" + by (metis (hide_lams, no_types) foundation17 foundation18' OclIncluding_valid_args_valid) + + have exclude_defined : "\\. \ \ \ X \ + (\ (\_. Abs_Set_0 \\{x \ \\Rep_Set_0 (X \)\\. x \ y \ \ P (\_. x) \ \ false \}\\)) \ = true \" + apply(subst defined_def, + simp add: false_def true_def bot_Set_0_def bot_fun_def null_Set_0_def null_fun_def) + by(subst Abs_Set_0_inject[OF ins_in_Set_0'''[simplified false_def]], + (simp add: OclValid_def bot_option_def null_option_def)+)+ + + have if_eq : "\x A B \. \ \ \ x \ \ \ (if x \ false then A else B endif) \ + (if x \ false then A else B endif)" + apply(simp add: StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n OclValid_def) + apply(subst (2) StrongEq_def) + by(subst cp_OclIf, simp add: cp_OclIf[symmetric] true_def) + + have OclSelect_body_bot: "\\. \ \ \ X \ \ \ \ y \ P y \ \ \ \ + (\x\\\Rep_Set_0 (X \)\\. P (\_. x) \ = \) \ \ = ?select \" + apply(drule ex_excluding1[where X = X and y = y and f = "\x \. x \ = \"], + (simp add: P_cp[symmetric])+) + apply(subgoal_tac "\ \ (\ \ ?select)", simp add: OclValid_def StrongEq_def true_def bot_fun_def) + apply(simp add: OclSelect_body_def) + apply(subst StrongEq_L_subst3[OF _ if_eq], simp, metis foundation18') + apply(simp add: OclValid_def, subst StrongEq_def, subst true_def, simp) + apply(subgoal_tac "\x\\\Rep_Set_0 (X->excluding(y) \)\\. P (\_. x) \ = \ \") + prefer 2 + apply (metis OCL_core.bot_fun_def foundation18') + apply(subst if_same[where d = "\"]) + apply (metis defined7 transform1) + apply(simp add: OclSelect_def bot_option_def bot_fun_def) + apply(subst invert_including) + by(simp add: OclSelect_def bot_option_def bot_fun_def)+ + + have d_and_v_inject : "\\ X y. (\ X and \ y) \ \ true \ \ (\ X and \ y) \ = false \" + by (metis bool_split defined5 defined6 defined_and_I foundation16 transform1 + invalid_def null_fun_def) + + have OclSelect_body_bot': "\\. (\ X and \ y) \ \ true \ \ \ = ?select \" + apply(drule d_and_v_inject) + apply(simp add: OclSelect_def OclSelect_body_def) + apply(subst cp_OclIf, subst cp_OclIncluding, simp add: false_def true_def) + apply(subst cp_OclIf[symmetric], subst cp_OclIncluding[symmetric]) + by (metis (lifting, no_types) OclIf_def foundation18 foundation18' invert_including) + + have conj_split2 : "\a b c \. ((a \ false) \ = false \ \ b) \ ((a \ false) \ = true \ \ c) \ + (a \ \ false \ \ b) \ (a \ = false \ \ c)" + by (metis OclValid_def defined7 foundation14 foundation22 foundation9) + + have defined_inject_true : "\\ P. (\ P) \ \ true \ \ (\ P) \ = false \" + apply(simp add: defined_def true_def false_def bot_fun_def bot_option_def + null_fun_def null_option_def) + by (case_tac " P \ = \ \ P \ = null", simp_all add: true_def) + + have cp_OclSelect_body : "\\. ?select \ = OclSelect_body P y (\_. OclSelect X->excluding(y) P \) \" + apply(simp add: OclSelect_body_def) + by(subst (1 2) cp_OclIf, subst (1 2) cp_OclIncluding, blast) + + have OclSelect_body_strict1 : "OclSelect_body P y invalid = invalid" + by(rule ext, simp add: OclSelect_body_def OclIf_def) + + have bool_invalid: "\(x::('\)Boolean) y \. \ (\ \ \ x) \ \ \ (x \ y) \ invalid" + by(simp add: StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n OclValid_def StrongEq_def true_def) + + have conj_comm : "\p q r. (p \ q \ r) = ((p \ q) \ r)" + by blast + + show ?thesis + apply(rule ext, rename_tac \) + apply(subst OclSelect_def) + apply(case_tac "(\ X->including(y)) \ = true \", simp) + apply(( subst ex_including + | subst in_including), + metis OclValid_def foundation5, + metis OclValid_def foundation5)+ + apply(simp add: Let_def) + + apply(subst (4) false_def, subst (4) bot_fun_def, simp add: bot_option_def P_cp[symmetric]) + (* *) + apply(case_tac "\ (\ \ (\ P y))") + apply(subgoal_tac "P y \ \ false \") + prefer 2 + apply (metis (hide_lams, no_types) foundation1 foundation18' valid4) + apply(simp) + (* *) + apply(subst conj_comm, rule conjI) + apply(drule_tac y = false in bool_invalid) + apply(simp only: OclSelect_body_def, + metis OclIf_def OclValid_def defined_def foundation2 foundation22 + bot_fun_def invalid_def) + (* *) + apply(drule foundation5[simplified OclValid_def], + subst al_including[simplified OclValid_def], + simp, + simp) + apply(simp add: P_cp[symmetric]) + apply (metis OCL_core.bot_fun_def foundation18') + + apply(simp add: foundation18' bot_fun_def OclSelect_body_bot OclSelect_body_bot') + (* *) + apply(subst (1 2) al_including, metis OclValid_def foundation5, metis OclValid_def foundation5) + apply(simp add: P_cp[symmetric], subst (4) false_def, subst (4) bot_option_def, simp) + apply(simp add: OclSelect_def OclSelect_body_def StrictRefEq\<^sub>B\<^sub>o\<^sub>o\<^sub>l\<^sub>e\<^sub>a\<^sub>n) + apply(subst (1 2 3 4) cp_OclIf, + subst (1 2 3 4) foundation18'[THEN iffD2, simplified OclValid_def], + simp, + simp only: cp_OclIf[symmetric] refl if_True) + apply(subst (1 2) cp_OclIncluding, rule conj_split2, simp add: cp_OclIf[symmetric]) + apply(subst (1 2 3 4 5 6 7 8) cp_OclIf[symmetric], simp) + apply(( subst ex_excluding1[symmetric] + | subst al_excluding1[symmetric] ), + metis OclValid_def foundation5, + metis OclValid_def foundation5, + simp add: P_cp[symmetric] bot_fun_def)+ + apply(simp add: bot_fun_def) + apply(subst (1 2) invert_including, simp+) + (* *) + apply(rule conjI, blast) + apply(intro impI conjI) + apply(subst OclExcluding_def) + apply(drule foundation5[simplified OclValid_def], simp) + apply(subst Abs_Set_0_inverse[OF diff_in_Set_0], fast) + apply(simp add: OclIncluding_def cp_valid[symmetric]) + apply((erule conjE)+, frule exclude_defined[simplified OclValid_def], simp) + apply(subst Abs_Set_0_inverse[OF ins_in_Set_0'''], simp+) + apply(subst Abs_Set_0_inject[OF ins_in_Set_0 ins_in_Set_0'], fast+) + (* *) + apply(simp add: OclExcluding_def) + apply(simp add: foundation10[simplified OclValid_def]) + apply(subst Abs_Set_0_inverse[OF diff_in_Set_0], simp+) + apply(subst Abs_Set_0_inject[OF ins_in_Set_0'' ins_in_Set_0'''], simp+) + apply(subgoal_tac "P (\_. y \) \ = false \") + prefer 2 + apply(subst P_cp[symmetric], metis OclValid_def foundation22) + apply(rule equalityI) + apply(rule subsetI, simp, metis) + apply(rule subsetI, simp) + (* *) + apply(drule defined_inject_true) + apply(subgoal_tac "\ (\ \ \ X) \ \ (\ \ \ y)") + prefer 2 + apply (metis bot_fun_def OclValid_def foundation18' OclIncluding_defined_args_valid valid_def) + apply(subst cp_OclSelect_body, subst cp_OclSelect, subst OclExcluding_def) + apply(simp add: OclValid_def false_def true_def, rule conjI, blast) + apply(simp add: OclSelect_invalid[simplified invalid_def] + OclSelect_body_strict1[simplified invalid_def]) + done +qed + +subsection{* OclReject *} + +lemma OclReject_mtSet_exec[simp,code_unfold]: "OclReject mtSet P = mtSet" +by(simp add: OclReject_def) + +lemma OclReject_including_exec[simp,code_unfold]: + assumes P_cp : "cp P" + shows "OclReject (X->including(y)) P = OclSelect_body (not o P) y (OclReject (X->excluding(y)) P)" + apply(simp add: OclReject_def comp_def, rule OclSelect_including_exec) +by (metis assms cp_intro''(5)) + +section{* Execution on Set's Operators (higher composition) *} + +subsection{* OclIncludes *} + +lemma OclIncludes_any[simp,code_unfold]: + "X->includes(X->any()) = (if \ X then + if \ (X->size()) then not(X->isEmpty()) + else X->includes(null) endif + else invalid endif)" +proof - + have defined_inject_true : "\\ P. (\ P) \ \ true \ \ (\ P) \ = false \" + apply(simp add: defined_def true_def false_def bot_fun_def bot_option_def + null_fun_def null_option_def) + by (case_tac " P \ = \ \ P \ = null", simp_all add: true_def) + + have valid_inject_true : "\\ P. (\ P) \ \ true \ \ (\ P) \ = false \" + apply(simp add: valid_def true_def false_def bot_fun_def bot_option_def + null_fun_def null_option_def) + by (case_tac "P \ = \", simp_all add: true_def) + + have notempty': "\\ X. \ \ \ X \ finite \\Rep_Set_0 (X \)\\ \ not (X->isEmpty()) \ \ true \ \ + X \ = Set{} \" + apply(case_tac "X \", rename_tac X', simp add: mtSet_def Abs_Set_0_inject) + apply(erule disjE, metis (hide_lams, no_types) bot_Set_0_def bot_option_def foundation17) + apply(erule disjE, metis (hide_lams, no_types) bot_option_def + null_Set_0_def null_option_def foundation17) + apply(case_tac X', simp, metis (hide_lams, no_types) bot_Set_0_def foundation17) + apply(rename_tac X'', case_tac X'', simp) + apply (metis (hide_lams, no_types) foundation17 null_Set_0_def) + apply(simp add: OclIsEmpty_def OclSize_def) + apply(subst (asm) cp_OclNot, subst (asm) cp_OclOr, subst (asm) cp_StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r, + subst (asm) cp_OclAnd, subst (asm) cp_OclNot) + apply(simp only: OclValid_def foundation20[simplified OclValid_def] + cp_OclNot[symmetric] cp_OclAnd[symmetric] cp_OclOr[symmetric]) + apply(simp add: Abs_Set_0_inverse split: split_if_asm) + by(simp add: true_def OclInt0_def OclNot_def StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r StrongEq_def) + + have B: "\X \. \ finite \\Rep_Set_0 (X \)\\ \ (\ (X->size())) \ = false \" + apply(subst cp_defined) + apply(simp add: OclSize_def) + by (metis OCL_core.bot_fun_def defined_def) + + show ?thesis + apply(rule ext, rename_tac \, simp only: OclIncludes_def OclANY_def) + apply(subst cp_OclIf, subst (2) cp_valid) + apply(case_tac "(\ X) \ = true \", + simp only: foundation20[simplified OclValid_def] cp_OclIf[symmetric], simp, + subst (1 2) cp_OclAnd, simp add: cp_OclAnd[symmetric]) + apply(case_tac "finite \\Rep_Set_0 (X \)\\") + apply(frule size_defined'[THEN iffD2, simplified OclValid_def], assumption) + apply(subst (1 2 3 4) cp_OclIf, simp) + apply(subst (1 2 3 4) cp_OclIf[symmetric], simp) + apply(case_tac "(X->notEmpty()) \ = true \", simp) + apply(frule OclNotEmpty_has_elt[simplified OclValid_def], simp) + apply(simp add: OclNotEmpty_def cp_OclIf[symmetric]) + apply(subgoal_tac "(SOME y. y \ \\Rep_Set_0 (X \)\\) \ \\Rep_Set_0 (X \)\\", simp add: true_def) + apply(metis OclValid_def Set_inv_lemma foundation18' null_option_def true_def) + apply(rule someI_ex, simp) + apply(simp add: OclNotEmpty_def cp_valid[symmetric]) + apply(subgoal_tac "\ (null \ \ \\Rep_Set_0 (X \)\\)", simp) + apply(subst OclIsEmpty_def, simp add: OclSize_def) + apply(subst cp_OclNot, subst cp_OclOr, subst cp_StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r, subst cp_OclAnd, + subst cp_OclNot, simp add: OclValid_def foundation20[simplified OclValid_def] + cp_OclNot[symmetric] cp_OclAnd[symmetric] cp_OclOr[symmetric]) + apply(frule notempty'[simplified OclValid_def], + (simp add: mtSet_def Abs_Set_0_inverse OclInt0_def false_def)+) + apply(drule notempty'[simplified OclValid_def], simp, simp) + apply (metis (hide_lams, no_types) empty_iff mtSet_rep_set) + (* *) + apply(frule B) + apply(subst (1 2 3 4) cp_OclIf, simp) + apply(subst (1 2 3 4) cp_OclIf[symmetric], simp) + apply(case_tac "(X->notEmpty()) \ = true \", simp) + apply(frule OclNotEmpty_has_elt[simplified OclValid_def], simp) + apply(simp add: OclNotEmpty_def OclIsEmpty_def) + apply(subgoal_tac "X->size() \ = \") + prefer 2 + apply (metis (hide_lams, no_types) OclSize_def) + apply(subst (asm) cp_OclNot, subst (asm) cp_OclOr, subst (asm) cp_StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r, + subst (asm) cp_OclAnd, subst (asm) cp_OclNot) + apply(simp add: OclValid_def foundation20[simplified OclValid_def] + cp_OclNot[symmetric] cp_OclAnd[symmetric] cp_OclOr[symmetric]) + apply(simp add: OclNot_def StrongEq_def StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r valid_def false_def true_def + bot_option_def bot_fun_def invalid_def) + + apply (metis OCL_core.bot_fun_def null_fun_def null_is_valid valid_def) + by(drule defined_inject_true, + simp add: false_def true_def OclIf_false[simplified false_def] invalid_def) +qed + +subsection{* OclSize *} + +lemma [simp,code_unfold]: "\ (Set{} ->size()) = true" +by simp + + +lemma [simp,code_unfold]: "\ ((X ->including(x)) ->size()) = (\(X->size()) and \(x))" +proof - + have defined_inject_true : "\\ P. (\ P) \ \ true \ \ (\ P) \ = false \" + apply(simp add: defined_def true_def false_def bot_fun_def bot_option_def + null_fun_def null_option_def) + by (case_tac " P \ = \ \ P \ = null", simp_all add: true_def) + + have valid_inject_true : "\\ P. (\ P) \ \ true \ \ (\ P) \ = false \" + apply(simp add: valid_def true_def false_def bot_fun_def bot_option_def + null_fun_def null_option_def) + by (case_tac "P \ = \", simp_all add: true_def) + + have OclIncluding_finite_rep_set : "\\. (\ X and \ x) \ = true \ \ + finite \\Rep_Set_0 (X->including(x) \)\\ = finite \\Rep_Set_0 (X \)\\" + apply(rule OclIncluding_finite_rep_set) + by(metis OclValid_def foundation5)+ + + have card_including_exec : "\\. (\ (\_. \\int (card \\Rep_Set_0 (X->including(x) \)\\)\\)) \ = + (\ (\_. \\int (card \\Rep_Set_0 (X \)\\)\\)) \" + by(simp add: defined_def bot_fun_def bot_option_def null_fun_def null_option_def) + + show ?thesis + apply(rule ext, rename_tac \) + apply(case_tac "(\ (X->including(x)->size())) \ = true \", simp del: OclSize_including_exec) + apply(subst cp_OclAnd, subst cp_defined, simp only: cp_defined[of "X->including(x)->size()"], + simp add: OclSize_def) + apply(case_tac "((\ X and \ x) \ = true \ \ finite \\Rep_Set_0 (X->including(x) \)\\)", simp) + apply(erule conjE, + simp add: OclIncluding_finite_rep_set[simplified OclValid_def] card_including_exec + cp_OclAnd[of "\ X" "\ x"] + cp_OclAnd[of "true", THEN sym]) + apply(subgoal_tac "(\ X) \ = true \ \ (\ x) \ = true \", simp) + apply(rule foundation5[of _ "\ X" "\ x", simplified OclValid_def], + simp only: cp_OclAnd[THEN sym]) + apply(simp, simp add: defined_def true_def false_def bot_fun_def bot_option_def) + + apply(drule defined_inject_true[of "X->including(x)->size()"], + simp del: OclSize_including_exec, + simp only: cp_OclAnd[of "\ (X->size())" "\ x"], + simp add: cp_defined[of "X->including(x)->size()" ] cp_defined[of "X->size()" ] + del: OclSize_including_exec, + simp add: OclSize_def card_including_exec + del: OclSize_including_exec) + apply(case_tac "(\ X and \ x) \ = true \ \ finite \\Rep_Set_0 (X \)\\", + simp add: OclIncluding_finite_rep_set[simplified OclValid_def] card_including_exec, + simp only: cp_OclAnd[THEN sym], + simp add: defined_def bot_fun_def) + + apply(split split_if_asm) + apply(simp add: OclIncluding_finite_rep_set[simplified OclValid_def] card_including_exec)+ + apply(simp only: cp_OclAnd[THEN sym], simp, rule impI, erule conjE) + apply(case_tac "(\ x) \ = true \", simp add: cp_OclAnd[of "\ X" "\ x"]) + by(drule valid_inject_true[of "x"], simp add: cp_OclAnd[of _ "\ x"]) +qed + +lemma [simp,code_unfold]: "\ ((X ->excluding(x)) ->size()) = (\(X->size()) and \(x))" +proof - + have defined_inject_true : "\\ P. (\ P) \ \ true \ \ (\ P) \ = false \" + apply(simp add: defined_def true_def false_def bot_fun_def bot_option_def + null_fun_def null_option_def) + by (case_tac " P \ = \ \ P \ = null", simp_all add: true_def) + + have valid_inject_true : "\\ P. (\ P) \ \ true \ \ (\ P) \ = false \" + apply(simp add: valid_def true_def false_def bot_fun_def bot_option_def + null_fun_def null_option_def) + by (case_tac "P \ = \", simp_all add: true_def) + + have OclExcluding_finite_rep_set : "\\. (\ X and \ x) \ = true \ \ + finite \\Rep_Set_0 (X->excluding(x) \)\\ = + finite \\Rep_Set_0 (X \)\\" + apply(rule OclExcluding_finite_rep_set) + by(metis OclValid_def foundation5)+ + + have card_excluding_exec : "\\. (\ (\_. \\int (card \\Rep_Set_0 (X->excluding(x) \)\\)\\)) \ = + (\ (\_. \\int (card \\Rep_Set_0 (X \)\\)\\)) \" + by(simp add: defined_def bot_fun_def bot_option_def null_fun_def null_option_def) + + show ?thesis + apply(rule ext, rename_tac \) + apply(case_tac "(\ (X->excluding(x)->size())) \ = true \", simp) + apply(subst cp_OclAnd, subst cp_defined, simp only: cp_defined[of "X->excluding(x)->size()"], + simp add: OclSize_def) + apply(case_tac "((\ X and \ x) \ = true \ \ finite \\Rep_Set_0 (X->excluding(x) \)\\)", simp) + apply(erule conjE, + simp add: OclExcluding_finite_rep_set[simplified OclValid_def] card_excluding_exec + cp_OclAnd[of "\ X" "\ x"] + cp_OclAnd[of "true", THEN sym]) + apply(subgoal_tac "(\ X) \ = true \ \ (\ x) \ = true \", simp) + apply(rule foundation5[of _ "\ X" "\ x", simplified OclValid_def], + simp only: cp_OclAnd[THEN sym]) + apply(simp, simp add: defined_def true_def false_def bot_fun_def bot_option_def) + + apply(drule defined_inject_true[of "X->excluding(x)->size()"], + simp, + simp only: cp_OclAnd[of "\ (X->size())" "\ x"], + simp add: cp_defined[of "X->excluding(x)->size()" ] cp_defined[of "X->size()" ], + simp add: OclSize_def card_excluding_exec) + apply(case_tac "(\ X and \ x) \ = true \ \ finite \\Rep_Set_0 (X \)\\", + simp add: OclExcluding_finite_rep_set[simplified OclValid_def] card_excluding_exec, + simp only: cp_OclAnd[THEN sym], + simp add: defined_def bot_fun_def) + + apply(split split_if_asm) + apply(simp add: OclExcluding_finite_rep_set[simplified OclValid_def] card_excluding_exec)+ + apply(simp only: cp_OclAnd[THEN sym], simp, rule impI, erule conjE) + apply(case_tac "(\ x) \ = true \", simp add: cp_OclAnd[of "\ X" "\ x"]) + by(drule valid_inject_true[of "x"], simp add: cp_OclAnd[of _ "\ x"]) +qed + +lemma [simp]: + assumes X_finite: "\\. finite \\Rep_Set_0 (X \)\\" + shows "\ ((X ->including(x)) ->size()) = (\(X) and \(x))" +by(simp add: size_defined[OF X_finite] del: OclSize_including_exec) + + +subsection{* OclForall *} + +lemma OclForall_rep_set_false: + assumes "\ \ \ X" + shows "(OclForall X P \ = false \) = (\x \ \\Rep_Set_0 (X \)\\. P (\\. x) \ = false \)" +by(insert assms, simp add: OclForall_def OclValid_def false_def true_def + bot_fun_def bot_option_def null_fun_def null_option_def) + +lemma OclForall_rep_set_true: + assumes "\ \ \ X" + shows "(\ \ OclForall X P) = (\x \ \\Rep_Set_0 (X \)\\. \ \ P (\\. x))" +proof - + have destruct_ocl : "\x \. x = true \ \ x = false \ \ x = null \ \ x = \ \" + apply(case_tac x) apply (metis bot_Boolean_def) + apply(rename_tac x', case_tac x') apply (metis null_Boolean_def) + apply(rename_tac x'', case_tac x'') apply (metis (full_types) true_def) + by (metis (full_types) false_def) + + have disjE4 : "\ P1 P2 P3 P4 R. + (P1 \ P2 \ P3 \ P4) \ (P1 \ R) \ (P2 \ R) \ (P3 \ R) \ (P4 \ R) \ R" + by metis + show ?thesis + apply(simp add: OclForall_def OclValid_def true_def false_def + bot_fun_def bot_option_def null_fun_def null_option_def split: split_if_asm) + apply(rule conjI, rule impI) apply (metis OCL_core.drop.simps option.distinct(1)) + apply(rule impI, rule conjI, rule impI) apply (metis option.distinct(1)) + apply(rule impI, rule conjI, rule impI) apply (metis OCL_core.drop.simps) + apply(intro conjI impI ballI) + proof - fix x show "\x\\\Rep_Set_0 (X \)\\. P (\_. x) \ \ \None\ \ + \x\\\Rep_Set_0 (X \)\\. \y. P (\_. x) \ = \y\ \ + \x\\\Rep_Set_0 (X \)\\. P (\_. x) \ \ \\False\\ \ + x \ \\Rep_Set_0 (X \)\\ \ P (\\. x) \ = \\True\\" + apply(erule_tac x = x in ballE)+ + by(rule disjE4[OF destruct_ocl[of "P (\\. x) \"]], + (simp add: true_def false_def null_fun_def null_option_def bot_fun_def bot_option_def)+) + apply_end(simp add: assms[simplified OclValid_def true_def])+ + qed +qed + +lemma OclForall_includes : + assumes x_def : "\ \ \ x" + and y_def : "\ \ \ y" + shows "(\ \ OclForall x (OclIncludes y)) = (\\Rep_Set_0 (x \)\\ \ \\Rep_Set_0 (y \)\\)" + apply(simp add: OclForall_rep_set_true[OF x_def], + simp add: OclIncludes_def OclValid_def y_def[simplified OclValid_def]) + apply(insert Set_inv_lemma[OF x_def], simp add: valid_def false_def true_def bot_fun_def) +by(rule iffI, simp add: subsetI, simp add: subsetD) + +lemma OclForall_not_includes : + assumes x_def : "\ \ \ x" + and y_def : "\ \ \ y" + shows "(OclForall x (OclIncludes y) \ = false \) = (\ \\Rep_Set_0 (x \)\\ \ \\Rep_Set_0 (y \)\\)" + apply(simp add: OclForall_rep_set_false[OF x_def], + simp add: OclIncludes_def OclValid_def y_def[simplified OclValid_def]) + apply(insert Set_inv_lemma[OF x_def], simp add: valid_def false_def true_def bot_fun_def) +by(rule iffI, metis set_rev_mp, metis subsetI) + +lemma OclForall_iterate: + assumes S_finite: "finite \\Rep_Set_0 (S \)\\" + shows "S->forAll(x | P x) \ = (S->iterate(x; acc = true | acc and P x)) \" +proof - + have and_comm : "comp_fun_commute (\x acc. acc and P x)" + apply(simp add: comp_fun_commute_def comp_def) + by (metis OclAnd_assoc OclAnd_commute) + + have ex_insert : "\x F P. (\x\insert x F. P x) = (P x \ (\x\F. P x))" + by (metis insert_iff) + + have destruct_ocl : "\x \. x = true \ \ x = false \ \ x = null \ \ x = \ \" + apply(case_tac x) apply (metis bot_Boolean_def) + apply(rename_tac x', case_tac x') apply (metis null_Boolean_def) + apply(rename_tac x'', case_tac x'') apply (metis (full_types) true_def) + by (metis (full_types) false_def) + + have disjE4 : "\ P1 P2 P3 P4 R. + (P1 \ P2 \ P3 \ P4) \ (P1 \ R) \ (P2 \ R) \ (P3 \ R) \ (P4 \ R) \ R" + by metis + + let ?P_eq = "\x b \. P (\_. x) \ = b \" + let ?P = "\set b \. \x\set. ?P_eq x b \" + let ?if = "\f b c. if f b \ then b \ else c" + let ?forall = "\P. ?if P false (?if P \ (?if P null (true \)))" + show ?thesis + apply(simp only: OclForall_def OclIterate_def) + apply(case_tac "\ \ \ S", simp only: OclValid_def) + apply(subgoal_tac "let set = \\Rep_Set_0 (S \)\\ in + ?forall (?P set) = + Finite_Set.fold (\x acc. acc and P x) true ((\a \. a) ` set) \", + simp only: Let_def, simp add: S_finite, simp only: Let_def) + apply(case_tac "\\Rep_Set_0 (S \)\\ = {}", simp) + apply(rule finite_ne_induct[OF S_finite], simp) + (* *) + apply(simp only: image_insert) + apply(subst comp_fun_commute.fold_insert[OF and_comm], simp) + apply (metis empty_iff image_empty) + apply(simp) + apply (metis OCL_core.bot_fun_def destruct_ocl null_fun_def) + (* *) + apply(simp only: image_insert) + apply(subst comp_fun_commute.fold_insert[OF and_comm], simp) + apply (metis (mono_tags) imageE) + + (* *) + apply(subst cp_OclAnd) apply(drule sym, drule sym, simp only:, drule sym, simp only:) + apply(simp only: ex_insert) + apply(subgoal_tac "\x. x\F") prefer 2 + apply(metis all_not_in_conv) + proof - fix x F show "(\ S) \ = true \ \ \x. x \ F \ + ?forall (\b \. ?P_eq x b \ \ ?P F b \) = + ((\_. ?forall (?P F)) and (\_. P (\\. x) \)) \" + apply(rule disjE4[OF destruct_ocl[where x = "P (\\. x) \"]]) + apply(simp_all add: true_def false_def OclAnd_def + null_fun_def null_option_def bot_fun_def bot_option_def) + by (metis (lifting) option.distinct(1))+ + apply_end(simp add: OclValid_def)+ + qed +qed + +lemma OclForall_cong: + assumes "\x. x \ \\Rep_Set_0 (X \)\\ \ \ \ P (\\. x) \ \ \ Q (\\. x)" + assumes P: "\ \ OclForall X P" + shows "\ \ OclForall X Q" +proof - + have def_X: "\ \ \ X" + by(insert P, simp add: OclForall_def OclValid_def bot_option_def true_def split: split_if_asm) + show ?thesis + apply(insert P) + apply(subst (asm) OclForall_rep_set_true[OF def_X], subst OclForall_rep_set_true[OF def_X]) + by (simp add: assms) +qed + +lemma OclForall_cong': + assumes "\x. x \ \\Rep_Set_0 (X \)\\ \ \ \ P (\\. x) \ \ \ Q (\\. x) \ \ \ R (\\. x)" + assumes P: "\ \ OclForall X P" + assumes Q: "\ \ OclForall X Q" + shows "\ \ OclForall X R" +proof - + have def_X: "\ \ \ X" + by(insert P, simp add: OclForall_def OclValid_def bot_option_def true_def split: split_if_asm) + show ?thesis + apply(insert P Q) + apply(subst (asm) (1 2) OclForall_rep_set_true[OF def_X], subst OclForall_rep_set_true[OF def_X]) + by (simp add: assms) +qed + +subsection{* Strict Equality *} + +lemma StrictRefEq\<^sub>S\<^sub>e\<^sub>t_defined : + assumes x_def: "\ \ \ x" + assumes y_def: "\ \ \ y" + shows "((x::('\,'\::null)Set) \ y) \ = + (x->forAll(z| y->includes(z)) and (y->forAll(z| x->includes(z)))) \" +proof - + have rep_set_inj : "\\. (\ x) \ = true \ \ + (\ y) \ = true \ \ + x \ \ y \ \ + \\Rep_Set_0 (y \)\\ \ \\Rep_Set_0 (x \)\\" + apply(simp add: defined_def) + apply(split split_if_asm, simp add: false_def true_def)+ + apply(simp add: null_fun_def null_Set_0_def bot_fun_def bot_Set_0_def) + + apply(case_tac "x \", rename_tac x') + apply(case_tac x', simp_all, rename_tac x'') + apply(case_tac x'', simp_all) + + apply(case_tac "y \", rename_tac y') + apply(case_tac y', simp_all, rename_tac y'') + apply(case_tac y'', simp_all) + + apply(simp add: Abs_Set_0_inverse) + by(blast) + + show ?thesis + apply(simp add: StrictRefEq\<^sub>S\<^sub>e\<^sub>t StrongEq_def + foundation20[OF x_def, simplified OclValid_def] + foundation20[OF y_def, simplified OclValid_def]) + apply(subgoal_tac "\\x \ = y \\\ = true \ \ \\x \ = y \\\ = false \") + prefer 2 + apply(simp add: false_def true_def) + (* *) + apply(erule disjE) + apply(simp add: true_def) + + apply(subgoal_tac "(\ \ OclForall x (OclIncludes y)) \ (\ \ OclForall y (OclIncludes x))") + apply(subst cp_OclAnd, simp add: true_def OclValid_def) + apply(simp add: OclForall_includes[OF x_def y_def] + OclForall_includes[OF y_def x_def]) + + (* *) + apply(simp) + + apply(subgoal_tac "OclForall x (OclIncludes y) \ = false \ \ + OclForall y (OclIncludes x) \ = false \") + apply(subst cp_OclAnd, metis OclAnd_false1 OclAnd_false2 cp_OclAnd) + apply(simp only: OclForall_not_includes[OF x_def y_def, simplified OclValid_def] + OclForall_not_includes[OF y_def x_def, simplified OclValid_def], + simp add: false_def) + by (metis OclValid_def rep_set_inj subset_antisym x_def y_def) +qed + +lemma StrictRefEq\<^sub>S\<^sub>e\<^sub>t_exec[simp,code_unfold] : +"((x::('\,'\::null)Set) \ y) = + (if \ x then (if \ y + then ((x->forAll(z| y->includes(z)) and (y->forAll(z| x->includes(z))))) + else if \ y + then false (* x'->includes = null *) + else invalid + endif + endif) + else if \ x (* null = ??? *) + then if \ y then not(\ y) else invalid endif + else invalid + endif + endif)" +proof - + have defined_inject_true : "\\ P. (\ (\ \ \ P)) = ((\ P) \ = false \)" + by (metis bot_fun_def OclValid_def defined_def foundation16 null_fun_def) + + have valid_inject_true : "\\ P. (\ (\ \ \ P)) = ((\ P) \ = false \)" + by (metis bot_fun_def OclIf_true' OclIncludes_charn0 OclIncludes_charn0' OclValid_def valid_def + foundation6 foundation9) + show ?thesis + apply(rule ext, rename_tac \) + (* *) + apply(simp add: OclIf_def + defined_inject_true[simplified OclValid_def] + valid_inject_true[simplified OclValid_def], + subst false_def, subst true_def, simp) + apply(subst (1 2) cp_OclNot, simp, simp add: cp_OclNot[symmetric]) + apply(simp add: StrictRefEq\<^sub>S\<^sub>e\<^sub>t_defined[simplified OclValid_def]) + by(simp add: StrictRefEq\<^sub>S\<^sub>e\<^sub>t StrongEq_def false_def true_def valid_def defined_def) +qed + +lemma StrictRefEq\<^sub>S\<^sub>e\<^sub>t_L_subst1 : "cp P \ \ \ \ x \ \ \ \ y \ \ \ \ P x \ \ \ \ P y \ + \ \ (x::('\,'\::null)Set) \ y \ \ \ (P x ::('\,'\::null)Set) \ P y" + apply(simp only: StrictRefEq\<^sub>S\<^sub>e\<^sub>t OclValid_def) + apply(split split_if_asm) + apply(simp add: StrongEq_L_subst1[simplified OclValid_def]) +by (simp add: invalid_def bot_option_def true_def) + +lemma OclIncluding_cong' : +shows "\ \ \ s \ \ \ \ t \ \ \ \ x \ + \ \ ((s::('\,'a::null)Set) \ t) \ \ \ (s->including(x) \ (t->including(x)))" +proof - + have cp: "cp (\s. (s->including(x)))" + apply(simp add: cp_def, subst cp_OclIncluding) + by (rule_tac x = "(\xab ab. ((\_. xab)->including(\_. x ab)) ab)" in exI, simp) + + show "\ \ \ s \ \ \ \ t \ \ \ \ x \ \ \ (s \ t) \ ?thesis" + apply(rule_tac P = "\s. (s->including(x))" in StrictRefEq\<^sub>S\<^sub>e\<^sub>t_L_subst1) + apply(rule cp) + apply(simp add: foundation20) apply(simp add: foundation20) + apply (simp add: foundation10 foundation6)+ + done +qed + +lemma OclIncluding_cong : "\(s::('\,'a::null)Set) t x y \. \ \ \ t \ \ \ \ y \ + \ \ s \ t \ x = y \ \ \ s->including(x) \ (t->including(y))" + apply(simp only:) + apply(rule OclIncluding_cong', simp_all only:) +by(auto simp: OclValid_def OclIf_def invalid_def bot_option_def OclNot_def split : split_if_asm) + +lemma const_StrictRefEq\<^sub>S\<^sub>e\<^sub>t_including : "const a \ const S \ const X \ + const (X \ S->including(a))" + apply(rule const_StrictRefEq\<^sub>S\<^sub>e\<^sub>t, assumption) +by(rule const_OclIncluding) + +section{* Test Statements *} + +lemma syntax_test: "Set{\,\} = (Set{}->including(\)->including(\))" +by (rule refl) + +text{* Here is an example of a nested collection. Note that we have +to use the abstract null (since we did not (yet) define a concrete +constant @{term null} for the non-existing Sets) :*} +lemma semantic_test2: +assumes H:"(Set{\} \ null) = (false::('\)Boolean)" +shows "(\::('\)st) \ (Set{Set{\},null}->includes(null))" +by(simp add: OclIncludes_execute\<^sub>S\<^sub>e\<^sub>t H) + +(* legacy---still better names ? +lemmas defined_charn = foundation16 +lemmas definedD = foundation17 +lemmas valid_charn = +lemmas validD = foundation19 +lemmas valid_implies_defined = foundation20 + end legacy *) + +lemma short_cut'[simp,code_unfold]: "(\ \ \) = false" + apply(rule ext) + apply(simp add: StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r StrongEq_def OclInt8_def OclInt6_def + true_def false_def invalid_def bot_option_def) +done + +lemma short_cut''[simp,code_unfold]: "(\ \ \) = false" + apply(rule ext) + apply(simp add: StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r StrongEq_def OclInt2_def OclInt1_def + true_def false_def invalid_def bot_option_def) +done +lemma short_cut'''[simp,code_unfold]: "(\ \ \) = false" + apply(rule ext) + apply(simp add: StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r StrongEq_def OclInt2_def OclInt1_def + true_def false_def invalid_def bot_option_def) +done + +text{* Elementary computations on Sets.*} + +declare OclSelect_body_def [simp] + +value "\ (\ \ \(invalid::('\,'\::null) Set))" +value "\ \ \(null::('\,'\::null) Set)" +value "\ (\ \ \(null::('\,'\::null) Set))" +value "\ \ \(Set{})" +value "\ \ \(Set{Set{\},null})" +value "\ \ \(Set{Set{\},null})" +value "\ \ (Set{\,\}->includes(\))" +value "\ (\ \ (Set{\}->includes(\)))" +value "\ (\ \ (Set{\,\}->includes(null)))" +value "\ \ (Set{\,null}->includes(null))" +value "\ \ (Set{null,\}->includes(null))" + +value "\ \ ((Set{})->forAll(z | \ `< z))" + +value "\ \ ((Set{\,\})->forAll(z | \ `< z))" +value "\ (\ \ ((Set{\,\})->exists(z | z `< \ )))" +value "\ (\ \ \(Set{\,null})->forAll(z | \ `< z))" +value "\ (\ \ ((Set{\,null})->forAll(z | \ `< z)))" +value "\ \ ((Set{\,null})->exists(z | \ `< z))" + +value "\ (\ \ (Set{null::'a Boolean} \ Set{}))" +value "\ (\ \ (Set{null::'a Integer} \ Set{}))" + +value "(\ \ (Set{\_. \\x\\} \ Set{\_. \\x\\}))" +value "(\ \ (Set{\_. \x\} \ Set{\_. \x\}))" + +(* TO BE DONE + why does this not work ? ? ? + une regle importante est dans simp, mais pas dans code_unfold ... *) + +lemma "\ (\ \ (Set{true} \ Set{false}))" by simp +lemma "\ (\ \ (Set{true,true} \ Set{false}))" by simp +lemma "\ (\ \ (Set{\} \ Set{\}))" by simp +lemma "\ \ (Set{\,null,\} \ Set{null,\})" by simp +lemma "\ \ (Set{\,null,\} <> Set{null,\})" by simp +lemma "\ \ (Set{Set{\,null}} \ Set{Set{null,\}})" by simp +lemma "\ \ (Set{Set{\,null}} <> Set{Set{null,\},null})" by simp +lemma "\ \ (Set{null}->select(x | not x) \ Set{null})" by simp +lemma "\ \ (Set{null}->reject(x | not x) \ Set{null})" by simp + +lemma "const (Set{Set{\,null}, invalid})" by(simp add: const_ss) + +(* +value "\ (\ \ (Set{true} \ Set{false}))" +value "\ (\ \ (Set{true,true} \ Set{false}))" +value "\ (\ \ (Set{\} \ Set{\}))" +value "\ \ (Set{\,null,\} \ Set{null,\})" +value "\ \ (Set{\,null,\} <> Set{null,\})" +value "\ \ (Set{Set{\,null}} \ Set{Set{null,\}})" +value "\ \ (Set{Set{\,null}} <> Set{Set{null,\},null})" +value "\ \ (Set{null}->select(x | not x) \ Set{null})" +value "\ \ (Set{null}->reject(x | not x) \ Set{null})" +*) +end diff --git a/OCL_main.thy b/OCL_main.thy new file mode 100644 index 0000000..426ee1b --- /dev/null +++ b/OCL_main.thy @@ -0,0 +1,57 @@ +(***************************************************************************** + * Featherweight-OCL --- A Formal Semantics for UML-OCL Version OCL 2.4 + * for the OMG Standard. + * http://www.brucker.ch/projects/hol-testgen/ + * + * OCL_main.thy --- + * This file is part of HOL-TestGen. + * + * Copyright (c) 2012-2013 Université Paris-Sud, 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. + ******************************************************************************) + +theory OCL_main +imports OCL_lib OCL_state OCL_tools +begin + + + +end + + + + + + + + + diff --git a/OCL_state.thy b/OCL_state.thy new file mode 100644 index 0000000..e69d8ec --- /dev/null +++ b/OCL_state.thy @@ -0,0 +1,1054 @@ +(***************************************************************************** + * Featherweight-OCL --- A Formal Semantics for UML-OCL Version OCL 2.4 + * for the OMG Standard. + * http://www.brucker.ch/projects/hol-testgen/ + * + * OCL_state.thy --- State Operations and Objects. + * This file is part of HOL-TestGen. + * + * Copyright (c) 2012-2013 Université Paris-Sud, France + * 2013 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. + ******************************************************************************) + +header{* Formalization III: State Operations and Objects *} + +theory OCL_state +imports OCL_lib +begin + +section{* Introduction: States over Typed Object Universes *} + +text{* + 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{* Recall: The Generic Structure of States *} +text{* Recall the foundational concept of an object id (oid), +which is just some infinite set.*} + +text{* +\begin{isar}[mathescape] +$\text{\textbf{type-synonym}}$ $\mathit{oid = nat}$ +\end{isar} +*} + +text{* Further, recall that states are pair of a partial map from oid's to elements of an +object universe @{text "'\"}---the heap---and a map to relations of objects. +The relations were encoded as lists of pairs to leave the possibility to have Bags, +OrderedSets or Sequences as association ends. *} +text{* This leads to the definitions: +\begin{isar}[mathescape] +record ('\)state = + heap :: "oid \ '\ " + assocs\<^sub>2 :: "oid \ (oid \ oid) list" + assocs\<^sub>3 :: "oid \ (oid \ oid \ oid) list" + +$\text{\textbf{type-synonym}}$ ('\)st = "'\ state \ '\ state" +\end{isar} +*} + +text{* Now we refine our state-interface. +In certain contexts, we will require that the elements of the object universe have +a particular structure; more precisely, we will require that there is a function that +reconstructs the oid of an object in the state (we will settle the question how to define +this function later). *} + +class object = fixes oid_of :: "'a \ oid" + +text{* Thus, if needed, we can constrain the object universe to objects by adding +the following type class constraint:*} +typ "'\ :: object" + +text{* The major instance needed are instances constructed over options: once an object, +options of objects are also objects. *} +instantiation option :: (object)object +begin + definition oid_of_option_def: "oid_of x = oid_of (the x)" + instance .. +end + +section{* Fundamental Predicates on Object: Strict 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 \" + +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.split_if_asm) + + +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{* Execution with Invalid or Null as Argument *} + +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) + +subsubsection{* Context Passing *} + +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]) + +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"]] + +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 @{text "\"} 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\<^sub>2= Map.empty, assocs\<^sub>3= Map.empty\, + \heap=Map.empty, assocs\<^sub>2= Map.empty, assocs\<^sub>3= 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_0 \\ 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_0_def null_fun_def null_Set_0_def) + apply(rule conjI) + apply(rule notI, subst (asm) Abs_Set_0_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(x))" +shows "\ \ not(x \ null)" +proof - + have B: "\ \ \ (OclAllInstances_generic pre_post H)" + by(insert A[THEN OCL_core.foundation6, + simplified OCL_lib.OclIncludes_defined_args_valid], auto) + have C: "\ \ \ x" + by(insert A[THEN OCL_core.foundation6, + simplified OCL_lib.OclIncludes_defined_args_valid], auto) + 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 OCL_lib.Set_0.Abs_Set_0_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(x))" +shows "\ \ \ (OclAllInstances_generic pre_post H) \ \ \ \ x" +apply(insert A[THEN OCL_core.foundation6, + simplified OCL_lib.OclIncludes_defined_args_valid]) +apply(simp add: OCL_core.foundation16 OCL_core.foundation18 invalid_def, erule conjE) +apply(insert A[THEN represented_generic_objects_nonnull]) +by(simp add: foundation24 null_fun_def) + + +text{* One way to establish the actual presence of an object representation in a state is:*} + +lemma represented_generic_objects_in_state: +assumes A: "\ \ (OclAllInstances_generic pre_post H)->includes(x)" +shows "x \ \ (Some o H) ` ran (heap(pre_post \))" +proof - + have B: "(\ (OclAllInstances_generic pre_post H)) \ = true \" + by(simp add: OCL_core.OclValid_def[symmetric] OclAllInstances_generic_defined) + have C: "(\ x) \ = true \" + by(insert A[THEN OCL_core.foundation6, + simplified OCL_lib.OclIncludes_defined_args_valid], + auto simp: OclValid_def) + have F: "Rep_Set_0 (Abs_Set_0 \\Some ` (H ` ran (heap (pre_post \)) - {None})\\) = + \\Some ` (H ` ran (heap (pre_post \)) - {None})\\" + by(subst OCL_lib.Set_0.Abs_Set_0_inverse,simp_all add: bot_option_def) + show ?thesis + apply(insert A) + apply(simp add: 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=empty, assocs\<^sub>2=A, assocs\<^sub>3=B\) \ OclAllInstances_generic pre_post Type \ Set{}" +proof - + have state_update_vs_allInstances_empty: + "(OclAllInstances_generic pre_post Type) (mk \heap=empty, assocs\<^sub>2=A, assocs\<^sub>3=B\) = + Set{} (mk \heap=empty, assocs\<^sub>2=A, assocs\<^sub>3=B\)" + by(simp add: OclAllInstances_generic_def mtSet_def) + show ?thesis + apply(simp only: OclValid_def, subst cp_StrictRefEq\<^sub>S\<^sub>e\<^sub>t, + simp add: state_update_vs_allInstances_empty) + apply(simp add: OclIf_def valid_def mtSet_def defined_def + bot_fun_def null_fun_def null_option_def bot_Set_0_def) + by(subst Abs_Set_0_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\<^sub>2=A, assocs\<^sub>3=B\) + = + ((OclAllInstances_generic pre_post Type)->including(\ _. \\ drop (Type Object) \\)) + (mk \heap=\',assocs\<^sub>2=A, assocs\<^sub>3=B\)" +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], + simp add: OclAllInstances_generic_def) + apply(subst Abs_Set_0_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\<^sub>2=A, assocs\<^sub>3=B\) + = + ((\_. (OclAllInstances_generic pre_post Type) + (mk \heap=\', assocs\<^sub>2=A, assocs\<^sub>3=B\))->including(\ _. \\ drop (Type Object) \\)) + (mk \heap=\'(oid\Object), assocs\<^sub>2=A, assocs\<^sub>3=B\)" + apply(subst state_update_vs_allInstances_generic_including', (simp add: assms)+, + subst cp_OclIncluding, + simp add: 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 + bot_fun_def null_fun_def bot_Set_0_def null_Set_0_def) + apply(subst (1 3) Abs_Set_0_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\<^sub>2=A, assocs\<^sub>3=B\) + = + (OclAllInstances_generic pre_post Type) + (mk \heap=\', assocs\<^sub>2=A, assocs\<^sub>3=B\)" +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\<^sub>2=A,assocs\<^sub>3=B\ \ P (OclAllInstances_generic pre_post Type)) = + (mk \heap=\', assocs\<^sub>2=A, assocs\<^sub>3=B\ \ 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 OCL_core.cp_validity, 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 OCL_core.cp_validity[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\<^sub>2=A,assocs\<^sub>3=B\ \ P (OclAllInstances_generic pre_post Type)) = + (mk \heap=\', assocs\<^sub>2=A, assocs\<^sub>3=B\ \ P ((OclAllInstances_generic pre_post Type) + ->including(\ _. \(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 OCL_core.cp_validity, 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(\_.\\\Type Object\\\) ?\" + apply(rule state_update_vs_allInstances_generic_including) + by(insert oid_def, auto simp: type_conform) + also have "... = ((\_. ?allInstances ?\')->including(\_. (\_.\\\Type Object\\\) ?\') ?\')" + by(subst const_OclIncluding[simplified const_def], simp+) + also have "... = (?allInstances->including(\ _. \Type Object\) ?\')" + apply(subst OCL_lib.cp_OclIncluding[symmetric]) + by(insert type_conform, auto) + finally have Y : "?allInstances ?\ = (?allInstances->including(\ _. \Type Object\) ?\')" + by auto + show ?thesis + apply(subst X) apply(subst OCL_core.cp_validity[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(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(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(x)" +shows "x \ \ (Some o H) ` ran (heap(snd \))" +by(rule represented_generic_objects_in_state[OF A[simplified OclAllInstances_at_post_def]]) + +lemma state_update_vs_allInstances_at_post_empty: +shows "(\, \heap=empty, assocs\<^sub>2=A, assocs\<^sub>3=B\) \ 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\<^sub>2=A, assocs\<^sub>3=B\) + = + ((Type .allInstances())->including(\ _. \\ drop (Type Object) \\)) + (\, \heap=\',assocs\<^sub>2=A, assocs\<^sub>3=B\)" +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\<^sub>2=A, assocs\<^sub>3=B\) + = + ((\_. (Type .allInstances()) + (\, \heap=\', assocs\<^sub>2=A, assocs\<^sub>3=B\))->including(\ _. \\ drop (Type Object) \\)) + (\, \heap=\'(oid\Object), assocs\<^sub>2=A, assocs\<^sub>3=B\)" +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\<^sub>2=A, assocs\<^sub>3=B\) + = + (Type .allInstances()) + (\, \heap=\', assocs\<^sub>2=A, assocs\<^sub>3=B\)" +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\<^sub>2=A,assocs\<^sub>3=B\) \ (P(Type .allInstances()))) = + ((\, \heap=\', assocs\<^sub>2=A, assocs\<^sub>3=B\) \ (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\<^sub>2=A,assocs\<^sub>3=B\) \ (P(Type .allInstances()))) = + ((\, \heap=\', assocs\<^sub>2=A, assocs\<^sub>3=B\) \ (P((Type .allInstances()) + ->including(\ _. \(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(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(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(x)" +shows "x \ \ (Some o H) ` ran (heap(fst \))" +by(rule represented_generic_objects_in_state[OF A[simplified OclAllInstances_at_pre_def]]) + + +lemma state_update_vs_allInstances_at_pre_empty: +shows "(\heap=empty, assocs\<^sub>2=A, assocs\<^sub>3=B\, \) \ 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\<^sub>2=A, assocs\<^sub>3=B\, \) + = + ((Type .allInstances@pre())->including(\ _. \\ drop (Type Object) \\)) + (\heap=\',assocs\<^sub>2=A, assocs\<^sub>3=B\, \)" +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\<^sub>2=A, assocs\<^sub>3=B\, \) + = + ((\_. (Type .allInstances@pre()) + (\heap=\', assocs\<^sub>2=A, assocs\<^sub>3=B\, \))->including(\ _. \\ drop (Type Object) \\)) + (\heap=\'(oid\Object), assocs\<^sub>2=A, assocs\<^sub>3=B\, \)" +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\<^sub>2=A, assocs\<^sub>3=B\, \) + = + (Type .allInstances@pre()) + (\heap=\', assocs\<^sub>2=A, assocs\<^sub>3=B\, \)" +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\<^sub>2=A,assocs\<^sub>3=B\, \) \ (P(Type .allInstances@pre()))) = + ((\heap=\', assocs\<^sub>2=A, assocs\<^sub>3=B\, \) \ (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\<^sub>2=A,assocs\<^sub>3=B\, \) \ (P(Type .allInstances@pre()))) = + ((\heap=\', assocs\<^sub>2=A, assocs\<^sub>3=B\, \) \ (P((Type .allInstances@pre()) + ->including(\ _. \(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(x) and H .allInstances()->includes(y)) or + (H .allInstances@pre()->includes(x) and H .allInstances@pre()->includes(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(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(x))" + apply(simp add: OclIncludes_def OclValid_def + OclAllInstances_at_pre_defined[simplified OclValid_def]) + by(subst cp_defined, simp) + have F: "Rep_Set_0 (Abs_Set_0 \\Some ` (H ` ran (heap (fst \)) - {None})\\) = + \\Some ` (H ` ran (heap (fst \)) - {None})\\" + by(subst OCL_lib.Set_0.Abs_Set_0_inverse,simp_all add: bot_option_def) + have F': "Rep_Set_0 (Abs_Set_0 \\Some ` (H ` ran (heap (snd \)) - {None})\\) = + \\Some ` (H ` ran (heap (snd \)) - {None})\\" + by(subst OCL_lib.Set_0.Abs_Set_0_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: split_if_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_0(X(\,\'))\\); + S = ((dom (heap \) \ dom (heap \')) - X') + in if (\ X) (\,\') = true (\,\') \ (\x\\\Rep_Set_0(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(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: split_if_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_0 (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(a| P a)) = (oid_of (x \) \ oid_of ` \\Rep_Set_0 (X \)\\)" +proof - + have P_null_bot: "\b. b = null \ b = \ \ + \ (\x\\\Rep_Set_0 (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 foundation17 + | (metis OCL_core.bot_fun_def OclValid_def Set_inv_lemma def_X def_x defined_def valid_def, + metis def_X' def_x foundation17)))+ + done + + have not_inj : "\x y. ((not x) \ = (not y) \) = (x \ = y \)" + by (metis foundation21 foundation22) + + have P_false : "\x\\\Rep_Set_0 (X \)\\. P (\_. x) \ = false \ \ + oid_of (x \) \ oid_of ` \\Rep_Set_0 (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: split_if_asm) + apply(subgoal_tac "x \ \ null \ x' \ null", simp) + apply (metis (mono_tags) OCL_core.drop.simps def_x foundation17 true_def) + by(simp add: invalid_def bot_option_def true_def)+ + + have P_true : "\x\\\Rep_Set_0 (X \)\\. P (\_. x) \ = true \ \ + oid_of (x \) \ oid_of ` \\Rep_Set_0 (X \)\\" + apply(subgoal_tac "\x'\\\Rep_Set_0 (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: split_if_asm) + apply(subgoal_tac "x \ \ null \ x' \ null", simp) + apply (metis def_X' def_x foundation17) + by(simp add: invalid_def bot_option_def false_def)+ + + have bool_split : "\x\\\Rep_Set_0 (X \)\\. P (\_. x) \ \ null \ \ + \x\\\Rep_Set_0 (X \)\\. P (\_. x) \ \ \ \ \ + \x\\\Rep_Set_0 (X \)\\. P (\_. x) \ \ false \ \ + \x\\\Rep_Set_0 (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) OCL_core.bot_fun_def OclNot4 OclValid_def foundation16 foundation18' + 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(x))->oclIsModifiedOnly()" + and oid_is_typerepr : "\ \ X->forAll(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: OclForall_def OclValid_def split: split_if_asm) + by(simp add: bot_option_def true_def) + + have def_X' : "\x. x \ \\Rep_Set_0 (X \)\\ \ x \ null" + apply(insert modifiesclause, simp add: OclIsModifiedOnly_def OclValid_def split: split_if_asm) + apply(case_tac \, simp split: split_if_asm) + apply(simp add: OclExcluding_def split: split_if_asm) + apply(subst (asm) (2) Abs_Set_0_inverse) + apply(simp, (rule disjI2)+) + apply (metis (hide_lams, 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 (hide_lams, no_types) def_x foundation17) + apply (metis (hide_lams, 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_0 (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: split_if_asm) + apply(subst (asm) (2) OclExcluding_def) + apply(drule foundation5[simplified OclValid_def true_def], simp) + apply(subst (asm) Abs_Set_0_inverse, simp) + apply(rule disjI2)+ + apply (metis (hide_lams, 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 (hide_lams, 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 + apply_end(simp add: OclSelf_at_post_def OclSelf_at_pre_def OclValid_def StrongEq_def true_def)+ +qed + + +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(x))->oclIsModifiedOnly()" + and oid_is_typerepr : "\ \ X->forAll(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(y | (H .allInstances()->includes(x) and H .allInstances()->includes(y)) or + (H .allInstances@pre()->includes(x) and H .allInstances@pre()->includes(y)))" + shows "\ \ (x @pre P \ (x @post P))" +proof - + have def_X : "\ \ \ X" + apply(insert oid_is_typerepr, simp add: OclForall_def OclValid_def split: split_if_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: split_if_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: split_if_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: split_if_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: split_if_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: split_if_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) + +end diff --git a/OCL_tools.thy b/OCL_tools.thy new file mode 100644 index 0000000..9b6fba1 --- /dev/null +++ b/OCL_tools.thy @@ -0,0 +1,46 @@ +(***************************************************************************** + * Featherweight-OCL --- A Formal Semantics for UML-OCL Version OCL 2.4 + * for the OMG Standard. + * http://www.brucker.ch/projects/hol-testgen/ + * + * OCL_tools.thy --- + * This file is part of HOL-TestGen. + * + * Copyright (c) 2012 Université Paris-Sud, 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. + ******************************************************************************) + +theory OCL_tools +imports OCL_core +begin + +end diff --git a/ROOT b/ROOT new file mode 100644 index 0000000..930242f --- /dev/null +++ b/ROOT @@ -0,0 +1,24 @@ +chapter AFP + +session Featherweight_OCL (AFP) = HOL + + description {* Featherweight-OCL *} + options [document = pdf, document_variants="document:outline=/proof,/ML"] + theories + "OCL_main" + "examples/Employee_AnalysisModel_OCLPart" + "examples/Employee_DesignModel_OCLPart" + files + "document/conclusion.tex" + "document/formalization.tex" + "document/hol-ocl-isar.sty" + "document/introduction.tex" + "document/lstisar.sty" + "document/prooftree.sty" + "document/root.bib" + "document/root.tex" + "document/figures/AbstractSimpleChair.pdf" + "document/figures/jedit.png" + "document/figures/pdf.png" + "document/figures/person.png" + "document/figures/pre-post.pdf" + diff --git a/config b/config new file mode 100644 index 0000000..20cb828 --- /dev/null +++ b/config @@ -0,0 +1,9 @@ +# -*- shell-script -*- + +# Get email when automated build fails. May be empty. +# values: "email1 email2 .. emailn" +NOTIFY="brucker@spamfence.net wolff@lri.fr frederic.tuong@lri.fr" + +# Participate in frequent (nightly) build (only for small submissions) +# values: "yes" "no" +FREQUENT="yes" diff --git a/document/conclusion.tex b/document/conclusion.tex new file mode 100644 index 0000000..11bd4e8 --- /dev/null +++ b/document/conclusion.tex @@ -0,0 +1,187 @@ +\part{Conclusion} + +\chapter{Conclusion} + +\section{Lessons Learned and Contributions} +We provided a typed and type-safe shallow embedding of the core of +UML~\cite{omg:uml-infrastructure:2011,omg:uml-superstructure:2011} and +OCL~\cite{omg:ocl:2012}. Shallow embedding means that types of OCL +were injectively, \ie, mapped by the embedding one-to-one to types in +Isabelle/HOL~\cite{nipkow.ea:isabelle:2002}. We followed the usual +methodology to build up the theory uniquely by conservative extensions +of all operators in a denotational style and to derive logical and +algebraic (execution) rules from them; thus, we can guarantee the +logical consistency of the library and instances of the class model +construction, \ie, closed-world object-oriented datatype theories, as +long as it follows the described methodology.\footnote{Our two + examples of \inlineisar+Employee_DesignModel+ (see + \autoref{ex:employee-design}) sketch how this construction can + be captured by an automated process.} Moreover, all derived +execution rules are by construction type-safe (which would be an +issue, if we had chosen to use an object universe construction in +Zermelo-Fraenkel set theory as an alternative approach to subtyping.). +In more detail, our theory gives answers and concrete solutions to a +number of open major issues for the UML/OCL standardization: +\begin{enumerate} +\item the role of the two exception elements \inlineisar+invalid+ and + \inlineisar+null+, the former usually assuming strict evaluation + while the latter ruled by non-strict evaluation. +\item the functioning of the resulting four-valued logic, together + with safe rules (for example \inlineisar+foundation9+ -- + \inlineisar+foundation12+ in \autoref{sec:localVal}) that allow a + reduction to two-valued reasoning as required for many automated + provers. The resulting logic still enjoys the rules of a strong + Kleene Logic in the spirit of the Amsterdam + Manifesto~\cite{cook.ea::amsterdam:2002}. +\item the complicated life resulting from the two necessary + equalities: the standard's ``strict weak referential equality'' as + default (written \inlineisar+_ \ _+ throughout this document) and + the strong equality (written \inlineisar+_ \ _+), which + follows the logical Leibniz principle that ``equals can be replaced + by equals.'' Which is not necessarily the case if + \inlineisar+invalid+ or objects of different states are involved. +\item a type-safe representation of objects and a clarification of the + old idea of a one-to-one correspondence between object + representations and object-id's, which became a state invariant. +\item a simple concept of state-framing via the novel operator + \inlineocl+_->oclIsModifiedOnly()+ and its consequences for strong + and weak equality. +\item a semantic view on subtyping clarifying the role of static and + dynamic type (aka \emph{apparent} and \emph{actual} type in Java + terminology), and its consequences for casts, dynamic type-tests, + and static types. +\item a semantic view on path expressions, that clarify the role of + \inlineisar+invalid+ and \inlineisar+null+ as well as the tricky + issues related to de-referentiation in pre- and post state. +\item an optional extension of the OCL semantics by \emph{infinite} + sets that provide means to represent ``the set of potential objects + or values'' to state properties over them (this will be an important + feature if OCL is intended to become a full-blown code annotation + language in the spirit of JML~\cite{levens.ea:jml:2007} for semi-automated code verification, + and has been considered desirable in the Aachen + Meeting~\cite{brucker.ea:summary-aachen:2013}). +\end{enumerate} +Moreover, we managed to make our theory in large parts executable, +which allowed us to include mechanically checked +\inlineisar+value+-statements that capture numerous corner-cases +relevant for OCL implementors. Among many minor issues, we thus +pin-pointed the behavior of \inlineocl+null+ in collections as well +as in casts and the desired \inlineocl+isKindOf+-semantics of +\inlineocl+allInstances()+. + + +\section{Lessons Learned} +While our paper and pencil arguments, given +in~\cite{brucker.ea:ocl-null:2009}, turned out to be essentially +correct, there had also been a lesson to be learned: If the logic is +not defined as a Kleene-Logic, having a structure similar to a +complete partial order (CPO), reasoning becomes complicated: several +important algebraic laws break down which makes reasoning in OCL +inherent messy and a semantically clean compilation of OCL formulae to +a two-valued presentation, that is amenable to animators like +KodKod~\cite{torlak.ea:kodkod:2007} or SMT-solvers like +Z3~\cite{moura.ea:z3:2008} completely impractical. Concretely, if the +expression \inlineocl{not(null)} is defined \inlineocl{invalid} (as is +the case in the present standard~\cite{omg:ocl:2012}), than standard +involution does not hold, \ie, \inlineocl{not(not(A))} = \inlineocl{A} +does not hold universally. Similarly, if \inlineocl{null and null} is +\inlineocl{invalid}, then not even idempotence \inlineocl{X and X} = +\inlineocl{X} holds. We strongly argue in favor of a lattice-like +organization, where \inlineocl{null} represents ``more information'' +than \inlineocl{invalid} and the logical operators are monotone with +respect to this semantical ``information ordering.'' + +A similar experience with prior paper and pencil arguments was our +investigation of the object-oriented data-models, in particular +path-expressions ~\cite{DBLP:conf/models/BruckerLTW13}. The final +presentation is again essentially correct, but the technical details +concerning exception handling lead finally to a continuation-passing +style of the (in future generated) definitions for accessors, casts +and tests. Apparently, OCL semantics (as many other ``real'' +programming and specification languages) is meanwhile too complex to +be treated by informal arguments solely. + +Featherweight OCL makes several minor deviations from the standard and +showed how the previous constructions can be made correct and +consistent, and the DNF-normalization as well as $\delta$-closure laws +(necessary for a transition into a two-valued presentation of OCL +specifications ready for interpretation in SMT solvers +(see~\cite{brucker.ea:ocl-testing:2010} for details)) are valid in +Featherweight OCL. + +\section{Conclusion and Future Work} +Featherweight OCL concentrates on formalizing the semantics of a core +subset of OCL in general and in particular on formalizing the +consequences of a four-valued logic (\ie, OCL versions that support, +besides the truth values \inlineocl{true} and \inlineocl{false} also +the two exception values \inlineocl{invalid} and \inlineocl{null}). + +In the following, we outline the necessary steps for turning +Featherweight OCL into a fully fledged tool for OCL, \eg, similar to +\holocl as well as for supporting test case generation similar to +{HOL}-TestGen~\cite{brucker.ea:hol-testgen:2009}. There are +essentially five extensions necessary: +\begin{itemize} +\item extension of the library to support all OCL data types, \eg, + \inlineocl{OrderedSet(T)} or \inlineocl{Sequence(T)}. This + formalization of the OCL standard library can be used for checking + the consistency of the formal semantics (known as ``Annex A'') with + the informal and semi-formal requirements in the normative part of + the OCL standard. +\item development of a compiler that compiles a textual or CASE + tool representation (\eg, using XMI or the textual syntax of + the USE tool~\cite{richters:precise:2002}) of class + models. Such compiler could also generate the necessary casts when + converting standard OCL to Featherweight OCL as well as providing + ``normalizations'' such as converting multiplicities of class + attributes to into OCL class invariants. +\item a setup for translating Featherweight OCL into a two-valued + representation as described + in~\cite{brucker.ea:ocl-testing:2010}. As, in real-world scenarios, + large parts of {UML}/{OCL} specifications are defined (\eg, + from the default multiplicity \inlineocl{1} of an attributes + \inlineocl{x}, we can directly infer that for all valid states + \inlineocl{x} is neither \inlineocl{invalid} nor \inlineocl{null}), + such a translation enables an efficient test case generation + approach. +\item a setup in Featherweight OCL of the Nitpick + animator~\cite{blanchette.ea:nitpick:2010}. It remains to be shown + that the standard, Kodkod~\cite{torlak.ea:kodkod:2007} based + animator in Isabelle can give a similar quality of animation as the + OCLexec Tool~\cite{krieger.ea:generative:2010} +\item a code-generator setup for Featherweight OCL for Isabelle's + code generator. For example, the Isabelle code generator supports + the generation of F\#, which would allow to use {OCL} + specifications for testing arbitrary .net-based applications. +\end{itemize} +The first two extensions are sufficient to provide a formal proof +environment for OCL 2.5 similar to \holocl while the remaining +extensions are geared towards increasing the degree of proof +automation and usability as well as providing a tool-supported test +methodology for {UML}/{OCL}. + + +Our work shows that developing a machine-checked formal semantics of +recent {OCL} standards still reveals significant +inconsistencies---even though this type of research is not new. In +fact, we started our work already with the 1.x series of {OCL}. The +reasons for this ongoing consistency problems of {OCL} standard are +manifold. For example, the consequences of adding an additional +exception value to OCL 2.2 are widespread across the whole language +and many of them are also quite subtle. Here, a machine-checked formal +semantics is of great value, as one is forced to formalize all details +and subtleties. Moreover, the standardization process of the {OMG}, +in which standards (\eg, the {UML} infrastructure and the {OCL} +standard) that need to be aligned closely are developed quite +independently, are prone to ad-hoc changes that attempt to align these +standards. And, even worse, updating a standard document by voting on +the acceptance (or rejection) of isolated text changes does not help +either. Here, a tool for the editor of the standard that helps to +check the consistency of the whole standard after each and every +modifications can be of great value as well. + + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "root" + diff --git a/document/figures/AbstractSimpleChair.mp b/document/figures/AbstractSimpleChair.mp new file mode 100644 index 0000000..736ea36 --- /dev/null +++ b/document/figures/AbstractSimpleChair.mp @@ -0,0 +1,83 @@ +input metafun; +boolean cmykcolors; +cmykcolors := false; +input latexmp; +setupLaTeXMP( +% preamblefile="preamble" + class="scrbook" + ,options="10pt" + ,fontencoding="T1" + ,inputencoding="latin1" + ,packages=("babel[ngerman,USenglish]" + &",lmodern,hol-ocl-isar") + ,preamble=("\renewcommand\familydefault{\ttdefault}") + ,mode=normal +% ,multicolor=enable + ); +boolean metauml_defaultLaTeX; +metauml_defaultLaTeX := true; +input metauml; + +color MaroonFifty; +MaroonFifty := cmyk(0.00, 0.435, 0.34, 0.16); + + +beginfig(1) + + +%% Role Hierarchie +AbstractClass.Role("Role")()(); +Class.Hearer("Hearer")()(); +Class.Speaker("Speaker")()(); +Class.Chair("Chair")()(); +Class.CoChair("CoCair")()(); + +topToBottom(30)(Role, Hearer, Speaker); +topToBottom(30)(CoChair, Chair); +leftToRight(25)(Hearer, CoChair); +drawObjects(Role, Hearer, Speaker); +drawObjects(CoChair, Chair); + +link(inheritance)(Hearer.n -- Role.s); +link(inheritance)(Speaker.n -- Hearer.s); +link(inheritance)(CoChair.w -- Hearer.e); +link(inheritance)(Chair.n -- CoChair.s); + + +Class.Person("Person")("+name:String")(); +Class.Participant("Participant")()(); +Participant.n = Person.e + (Role.w - Person.e)/2 + (0,-30); +leftToRight(100)(Person, Role); + +topToBottom(47)(Person, Session); +Class.Session("Session")("+name:String") +( +%"+invite(p:Person):OclVoid", + "+findRole(p:Person):Role"); +drawObjects(Person, Session,Participant); + + +% AssocClass +link(association) (Person.e -- Role.w); +item(iAssoc)("person")(obj.sw = Person.e); +item(iAssoc)("0..*")(obj.nw = Person.e); +% +item(iAssoc)("role")(obj.se = Role.w); +item(iAssoc)("0..*")(obj.ne = Role.w); + +item(iAssoc)("0..*")(obj.ne = Participant.w); + +link(dashedLink)(Participant.n -- (Person.e+(Role.w-Person.e)/2)); +path p; +p = fullcircle scaled 6bp shifted (Person.e+(Role.w-Person.e)/2); +fill p withcolor white; +draw p; +%%% + +link(association) (pathManhattanX(Participant.w,(Session.n+(-10,0)))); +item(iAssoc)("session")(obj.sw = Session.n+(-10,0)); +item(iAssoc)("0..1")(obj.se = Session.n+(-10,0)); + +endfig; + +end diff --git a/document/figures/AbstractSimpleChair.pdf b/document/figures/AbstractSimpleChair.pdf new file mode 100644 index 0000000000000000000000000000000000000000..005916bec09a60fc86c577daf03b391232a726b1 GIT binary patch literal 26644 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 AKmY&$ literal 0 HcmV?d00001 diff --git a/document/figures/jedit.png b/document/figures/jedit.png new file mode 100644 index 0000000000000000000000000000000000000000..b188889dc25efbbb16399f7404b9ecc1d6af6414 GIT binary patch literal 48776 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 literal 0 HcmV?d00001 diff --git a/document/figures/pre-post.pdf b/document/figures/pre-post.pdf new file mode 100644 index 0000000000000000000000000000000000000000..bfea5d7e001e4f46426c2b0da3f96af7ab6906cd GIT binary patch literal 25851 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 +\newcommand{\oP}{\mathopen\MathOcl{\mathtt{(}}} +\newcommand{\cP}{\mathopen\MathOcl{\mathtt{)}}} +\newcommand{\OclArg}[1]{\oP #1\cP} +\newcommand{\OclSpot}{\mathopen\MathOcl{\spot}} +\newcommand{\OclMid}{\mathop\MathOcl{\mid}} +\renewcommand{\isasymbullet}{\ensuremath{\OclSpot}} + +% ; ****************************** + %; * Lifting * + %; ****************************** + + \ifthenelse{\boolean{isar@mnsymbol}}{% + \newHolOcl{LiftLeft}{\mathopen}{\llcorner} + \newHolOcl{LiftRight}{\mathclose}{\lrcorner} + \newHolOcl{DropLeft}{\mathopen}{\ulcorner} + \newHolOcl{DropRight}{\mathclose}{\urcorner} + }{ + \newHolOcl{LiftLeft}{\mathopen} + {\leavevmode\lower.6ex\hbox{$\llcorner$}\kern-.20em} + \newHolOcl{LiftRight}{\mathclose} + {\leavevmode\kern-.20em\lower.6ex\hbox{$\lrcorner$}} + \newHolOcl{DropLeft}{\mathopen} + {\leavevmode\lower-.2ex\hbox{$\ulcorner$}\kern-.18em} + \newHolOcl{DropRight}{\mathclose} + {\leavevmode\kern-.18em\lower-.2ex\hbox{$\urcorner$}} +} + % \newHolOcl{DropLeft}{\mathopen}{\ulcorner} + % \newHolOcl{DropRight}{\mathclose}{\urcorner} + %; ****************************** + %; * OclAny * + %; ****************************** + % \newcommand{\isasymMathOclAny}{} + \newOcl{IsNew}{\mathbin}{.oclIsNew()} + \newMathOcl{IsNew}{\mathbin}{\isasymOclIsNew} + \newOcl{AsType}{\mathbin}{.oclAsType} + \newMathOcl{AsType}{\mathbin}{\isasymOclAsType} + \newOcl{IsTypeOf}{\mathbin}{.oclIsTypeOf} + \newMathOcl{IsTypeOf}{\mathbin}{\isasymOclIsTypeOf} + \newOcl{IsType}{\mathbin}{.oclIsTypeOf} + \newMathOcl{IsType}{\mathbin}{\isasymOclIsType} + \newOcl{IsKindOf}{\mathbin}{.oclIsKindOf} + \newMathOcl{IsKindOf}{\mathbin}{\isasymOclIsKindOf} +% \newOcl{AllInstances}{\mathbin}{.AllInstances()} +% \newMathOcl{AllInstances}{\mathbin}{\isasymOclAllInstances} + %; ****************************** + %; * OCL Boolean * + %; ****************************** + \newMathOcl{Valid}{\mathrel}{\vDash} + \newOcl{Valid}{\mathrel}{Valid} + \newOcl{LocalValid}{\mathrel}{OclValid} + \ifthenelse{\boolean{isar@mnsymbol}}{% + \newMathOcl{True}{\mathord}{\mathocl{t}} + \newOcl{True}{\mathord}{true} + \newMathOcl{False}{\mathord}{\mathocl{f}} + \newOcl{False}{\mathord}{false} + } + {% + \newMathOcl{True}{\mathord}{\mathocl{T}} + \newOcl{True}{\mathord}{true} + \newMathOcl{False}{\mathord}{\mathocl{F}} + \newOcl{False}{\mathord}{false} + } + \newMathOcl{Not}{\mathop}{\lnot} + \newOcl{Not}{\mathop}{not\ap} + + \newMathOcl{And}{\mathbin}{\wedge} + \newOcl{And}{\mathbin}{\ap and} + \newMathOcl{Or}{\mathbin}{\vee} + \newOcl{Or}{\mathbini}{\ap or \ap} + \newMathOcl{Xor}{\mathbin}{\oplus} + \newOcl{Xor}{\mathbin}{\ap xor\ap} + + \newMathOcl{Sand}{\mathbin}{\dot{\wedge}} + \newOcl{Sand}{\mathbin}{\ap sand\ap} + \newMathOcl{Sor}{\mathbin}{\dot{\vee}} + \newOcl{Sor}{\mathbini}{\ap sor\ap} + \newMathOcl{Sxor}{\mathbin}{\dot{\oplus}} + \newOcl{Sxor}{\mathbin}{\ap sxor\ap} + + \newMathOcl{If}{\mathop}{\mathocl{if}} + \newOcl{If}{\mathopen}{if} + \newMathOcl{Then}{\mathop}{\mathocl{then}} + \newOcl{Then}{\mathbin}{then} + \newMathOcl{Else}{\mathop}{\mathocl{else}} + \newOcl{Else}{\mathbin}{else} + \newMathOcl{Endif}{\mathop}{\mathocl{endif}} + \newOcl{Endif}{\mathclose}{endif} + \newMathOcl{Let}{\mathop}{\mathocl{let}} + \newOcl{Let}{\mathopen}{let} + \newMathOcl{In}{\mathop}{\mathocl{in}} + \newOcl{In}{\mathopen}{in} + \newMathOcl{End}{\mathop}{\mathocl{end}} + \newOcl{End}{\mathopen}{end} + + \newMathOcl{Implies}{\mathbin}{\longrightarrow} + \newOcl{Implies}{\mathbin}{\ap implies\ap} + + \newMathOcl{Simplies}{\mathbin}{\dot{\longrightarrow}} + \newOcl{Simplies}{\mathbin}{\ap simplies\ap} + + \newMathOcl{VImplies}{\mathbin}{\stackrel{1}{\longrightarrow}} + \newOcl{VImplies}{\mathbin}{\ap implies1\ap} + \newMathOcl{VVImplies}{\mathbin}{\stackrel{2}{\longrightarrow}} + \newOcl{VVImplies}{\mathbin}{\ap implies2\ap} + \newMathOcl{IsDefined}{\mathop}{\partial} + \newOcl{IsDefined}{\mathop}{.IsDefined()} +\ifthenelse{\boolean{isar@mnsymbol}}{% + \newMathOcl{IsUndefined}{\mathop}{\not\partial}% +}{% + \newMathOcl{IsUndefined}{\mathop}{\not\!\partial}% +} +\newOcl{IsUndefined}{\mathop}{.oclIsUndefined()} + %; ****************************** + %; * OCL Real and Integer * + %; ****************************** + \newOcl{Less}{\mathrel}{\ensuremath{<}} + \newMathOcl{Less}{\mathrel}{\isasymOclLess} + \newOcl{Le}{\mathrel}{\ensuremath{<=}} + \newMathOcl{Le}{\mathrel}{\leq} + \newOcl{Greater}{\mathrel}{\ensuremath{>}} + \newMathOcl{Greater}{\mathrel}{\isasymOclGreater} + \newOcl{Ge}{\mathrel}{\ensuremath{>=}} + \newMathOcl{Ge}{\mathrel}{\geq} + \newOcl{Abs}{\mathbin}{.abs()} + \newMathOcl{AbsLeft}{\mathopen}{\lvert} + \newMathOcl{AbsRight}{\mathclose}{\rvert} + \newMathOcl{Min}{\mathop}{\mathrm{min}} + \newOcl{Min}{\mathrel}{.min} + \newMathOcl{Max}{\mathop}{\mathrm{max}} + \newOcl{Max}{\mathrel}{.max} + \newMathOcl{Mod}{\mathop}{\mathrm{mod}} + \newOcl{Mod}{\mathrel}{.mod} + \newMathOcl{Div}{\mathop}{\mathrm{div}} + \newOcl{Div}{\mathrel}{.div} + \newOcl{Floor}{\mathbin}{.floor()} + \newMathOcl{FloorLeft}{\mathopen}{\lfloor} + \newMathOcl{FloorRight}{\mathclose}{\rfloor} + \newOcl{Round}{\mathbin}{.round()} + \newMathOcl{RoundLeft}{\mathopen}{\lceil} + \newMathOcl{RoundRight}{\mathclose}{\rceil} + %; ****************************** + %; * OclUndefined * + %; ****************************** + \newMathOcl{Undefined}{\mathord}{\bot} + \newOcl{Undefined}{\mathord}{OclUndefined} + %; ****************************** + %; * OCL String * + %; ****************************** + \newMathOcl{Concat}{\mathbin}{^\frown} + \newOcl{Concat}{\mathbin}{.concat} + \newOcl{Substring}{\mathop}{.substring} + \newMathOcl{Substring}{\mathop}{\isasymOclSubstring} + \newOcl{ToInteger}{\mathop}{.toInteger()} + \newMathOcl{ToInteger}{\mathop}{\isasymOclToInteger} + \newOcl{ToReal}{\mathop}{.toReal()} + \newMathOcl{ToReal}{\mathop}{\isasymOclToReal} + \newOcl{ToUpper}{\mathop}{.toUpper()} + \newMathOcl{ToUpper}{\mathop}{\isasymOclToUpper} + \newOcl{ToLower}{\mathop}{.toLowert()} + \newMathOcl{ToLower}{\mathop}{\isasymOclToLower} + + %; ****************************** + %; * OCL Collection * + %; ****************************** + \newMathOcl{MtSet}{\mathord}{\emptyset} + \newOcl{MtSet}{\mathord}{\{\}} + \newMathOcl{MtSequence}{\mathord}{[]} + \newOcl{MtSequence}{\mathord}{[]} + \newMathOcl{MtBag}{\mathord}{\Lbag\Rbag} + \newOcl{MtBag}{\mathord}{Bag\{\}} + \newMathOcl{MtOrderedSet}{\mathord}{\langle\rangle} + \newOcl{MtOrderedSet}{\mathord}{OrderedSet\{\}} + \newOcl{Size}{\mathbin}{\aarrow size()} + \newMathOcl{SizeLeft}{\mathopen}{\lVert} + \newMathOcl{SizeRight}{\mathclose}{\rVert} + \newMathOcl{Includes}{\mathbin}{\in} + \newOcl{Includes}{\mathbin}{\aarrow includes} + \newMathOcl{Excludes}{\mathbin}{\not\in}%\nin} + \newOcl{Excludes}{\mathbin}{\aarrow excludes} + \newOcl{Flatten}{\mathbin}{\aarrow flatten} + \newMathOcl{FlattenLeft}{\mathbin}{\llceil} + \newMathOcl{FlattenRight}{\mathbin}{\rrceil} + \newOcl{Sum}{\mathbin}{\aarrow sum} + \newMathOcl{Sum}{\mathbin}{\isasymOclSum} + \newOcl{AsSet}{\mathop}{\aarrow asSet()} + \newMathOcl{AsSet}{\mathop}{\isasymOclAsSet} + \newOcl{AsSequence}{\mathop}{\aarrow asSequence()} + \newMathOcl{AsSequence}{\mathop}{\isasymOclAsSequence} + \newOcl{AsBag}{\mathbin}{\aarrow asBag()} + \newMathOcl{AsBag}{\mathop}{\isasymOclAsBag} + \newOcl{AsOrderedSet}{\mathbin}{\aarrow asOrderedSet()} + \newMathOcl{AsOrderedSet}{\mathbin}{\isasymOclAsOrderedSet} + \newMathOcl{ForAll}{\mathop}{\forall} + \newOcl{ForAll}{\mathbin}{\aarrow forall} + \newMathOcl{Exists}{\mathop}{\exists} + \newOcl{Exists}{\mathbin}{\aarrow exists} + \newOcl{Select}{\mathop}{\aarrow select} + \newcommand{\isasymMathOclSelectRight}{\ensuremath{\mathopen{\MathOcl{\rrparenthesis}}}} + \newcommand{\isasymMathOclSelectLeft}{\ensuremath{\mathclose{\MathOcl{\llparenthesis}}}} + \newOcl{Reject}{\mathop}{\aarrow reject} + \newcommand{\isasymMathOclRejectRight}{\ensuremath{\mathopen{\MathOcl{\llparenthesis}}}} + \newcommand{\isasymMathOclRejectLeft}{\ensuremath{\mathclose{\MathOcl{\rrparenthesis}}}} + \newOcl{Collect}{\mathbin}{\aarrow collect} + % \newMathOcl{Collect}{\mathop}{\isasymOclCollect} + \newcommand{\isasymMathOclCollectRight}{\ensuremath{\mathopen{\MathOcl{|\!\}}}}} + \newcommand{\isasymMathOclCollectLeft}{\ensuremath{\mathclose{\MathOcl{\{\!|}}}} + \newOcl{CollectNested}{\mathbin}{\aarrow collectNested} + \newcommand{\isasymMathOclCollectNestedRight}{\ensuremath{\mathopen{\MathOcl{|\!\}\!\}}}}} + \newcommand{\isasymMathOclCollectNestedLeft}{\ensuremath{\mathclose{\MathOcl{\{\!\{\!|}}}} + \newOcl{Iterate}{\mathbin}{\aarrow iterate} + \newMathOcl{Iterate}{\mathop}{\isasymOclIterate} + \newOcl{IsUnique}{\mathbin}{\aarrow isUnique} + \newMathOcl{IsUnique}{\mathbin}{\isasymOclIsUnique} + \newOcl{One}{\mathbin}{\aarrow one} + \newMathOcl{One}{\mathop}{\isasymOclOne} + \newOcl{Any}{\mathbin}{\aarrow any} + \newMathOcl{Any}{\mathop}{\isasymOclAny} + \newOcl{Count}{\mathbin}{\aarrow count} + \newMathOcl{Count}{\mathop}{\isasymOclCount} + \newOcl{IncludesAll}{\mathbin}{\aarrow includesAll} + \newMathOcl{IncludesAll}{\mathop}{\subseteq} + \newOcl{ExcludesAll}{\mathbin}{\aarrow excludesAll} + \newMathOcl{ExcludesAll}{\mathop}{\supset\kern-0.5em\subset} + \newOcl{IsEmpty}{\mathbin}{\aarrow isEmpty()} + \newMathOcl{IsEmpty}{\mathop}{\emptyset \isasymMathOclStrictEq} + \newOcl{NotEmpty}{\mathbin}{\aarrow notEmpty()} + \newMathOcl{NotEmpty}{\mathop}{\emptyset \isasymMathOclStrictNotEq} + + \newOcl{SortedBy}{\mathbin}{\aarrow sortedBy} + \newMathOcl{SortedBy}{\mathbin}{\isasymOclSortedBy} + + + \newOcl{Sum}{\mathbin}{\aarrow sum()} + \newMathOcl{Sum}{\mathop}{\isasymOclSum} + \newOcl{Product}{\mathbin}{\aarrow product} + \newMathOcl{Product}{\mathop}{\times} + + \newOcl{Including}{\mathbin}{\aarrow including} + \newMathOcl{Including}{\mathop}{\operatorname{insert}} + \newOcl{Excluding}{\mathbin}{\aarrow excluding} + \newMathOcl{Excluding}{\mathop}{\isasymOclExcluding} + \newMathOcl{SymmetricDifference}{\mathbin}{\ominus} + \newOcl{SymmetricDifference}{\mathbin}{\aarrow symmetricDiffernce} + \newMathOcl{Union}{\mathbin}{\cup} + \newOcl{Union}{\mathbin}{\aarrow union} + + \newMathOcl{Intersection}{\mathbin}{\cap} + \newOcl{Intersection}{\mathbin}{\aarrow intersection} + \newMathOcl{Complement}{\mathop}{^{-1}} + \newOcl{Complement}{\mathop}{\aarrow complement()} + + \newMathOcl{At}{\mathop}{\natural} + \newOcl{At}{\mathop}{\aarrow at} + \newMathOcl{First}{\mathop}{\natural 1} + \newOcl{First}{\mathop}{\aarrow first()} + \newMathOcl{Last}{\mathop}{\natural \$} + \newOcl{Last}{\mathop}{\aarrow last()} + + + \newOcl{IndexOf}{\mathbin}{\aarrow indexOf} + \newMathOcl{IndexOf}{\mathop}{\natural ?} + + \newOcl{InsertAt}{\mathbin}{\aarrow insertAt} + \newMathOcl{InsertAt}{\mathop}{\isasymOclInsertAt} + + \newOcl{SubOrderedSet}{\mathbin}{\aarrow subOrderedSet} + \newMathOcl{SubOrderedSet}{\mathop}{\isasymOclSubOrderedSet} + \newOcl{SubSequence}{\mathbin}{\aarrow subSequence} + \newMathOcl{SubSequence}{\mathop}{\isasymOclSubSequence} + + + + %; ****************************** + %; * OCL Set * + %; ****************************** + %; ****************************** + %; * OCL OrderedSet * + %; ****************************** + \newMathOcl{Prepend}{\mathop}{\#} + \newOcl{Prepend}{\mathop}{\aarrow prepend} + \newMathOcl{Append}{\mathop}{@} + \newOcl{Append}{\mathop}{\aarrow append} + + + %; ****************************** + %; * OCL Bag * + %; ****************************** + %; ****************************** + %; * OCL Sequence * + %; ****************************** + %; ****************************** + %; * OCL Logic * + %; ****************************** + \newOcl{StrictEq}{\mathrel}{==} + \newMathOcl{StrictEq}{\mathrel}{\doteq} + \newOcl{StrongEq}{\mathrel}{=} + \newMathOcl{StrongEq}{\mathrel}{\triangleq} + + \newOcl{StrongNotEq}{\mathrel}{\not=} + \newMathOcl{StrongNotEq}{\mathrel}{\not\triangleq} + + \newOcl{StrictNotEq}{\mathrel}{<>} + \newMathOcl{StrictNotEq}{\mathrel}{\not\doteq} + + + \newOcl{StrictValueEq}{\mathrel}{\ensuremath{\sim==}} + \newMathOcl{StrictValueEq}{\mathrel}{\dot{\simeq}} + \newOcl{StrongValueEq}{\mathrel}{\ensuremath{\sim=}} + \ifthenelse{\boolean{isar@mnsymbol}}{% + \newMathOcl{StrongValueEq}{\mathrel}{\stackrel{\smalltriangleup}{\simeq}}% + }{% + \newMathOcl{StrongValueEq}{\mathrel}{\stackrel{\vartriangle}{\simeq}}% + } + \newOcl{StrictDeepValueEq}{\mathrel}{\ensuremath{\sim==\sim}} + \newMathOcl{StrictDeepValueEq}{\mathrel}{\dot{\approxeq}} + \newOcl{StrongDeepValueEq}{\mathrel}{\ensuremath{\sim=\sim}} + \ifthenelse{\boolean{isar@mnsymbol}}{% + \newMathOcl{StrongDeepValueEq}{\mathrel}{\stackrel{\smalltriangleup}{\approxeq}}% + }{% + \newMathOcl{StrongDeepValueEq}{\mathrel}{\stackrel{\vartriangle}{\approxeq}}% + } + %\newOcl{RefEq}{\mathrel}{~=} + % \newMathOcl{RefEq}{\mathrel}{\simeq} + %; ****************************** + %; * OCL State * + %; ****************************** + % \newMathOcl{IsTypeOf}{} + % \newMathOcl{Iny/sNew}{} + % \newMathOcl{IsKind}{} + % \newMathOcl{AsType}{} + % \newMathOcl{InState}{} + % \newMathOcl{AllInstances}{} + % \newMathOcl{MethodCall}{} + % \newMathOcl{FeatureCall}{} + + \newOcl{IsModifiedOnly}{\mathbin}{\aarrow oclIsModifiedOnly()} + \newMathOcl{IsModifiedOnly}{\mathbin}{\isasymOclIsModifiedOnly} + + \newOcl{AllInstances}{\mathbin}{.allInstances()} + \newMathOcl{AllInstances}{\mathbin}{\isasymOclAllInstances} + + \newOcl{KindSetOf}{\mathbin}{::kindSetOf()} + \newMathOcl{KindSetOf}{\mathbin}{\isasymOclKindSetOf} + + \newOcl{TypeSetOf}{\mathbin}{::typeSetOf()} + \newMathOcl{TypeSetOf}{\mathbin}{\isasymOclTypeSetOf} + + \newOcl{AllInstancesATpre}{\mathbin}{.allInstances@pre()} + \newMathOcl{AllInstancesATpre}{\mathbin}{\isasymOclAllInstancesATpre} + + \newOcl{ATpre}{\mathbin}{@pre} + \newMathOcl{ATpre}{\mathbin}{\isasymOclATpre} + +%%% undefining commands that should never be used directly: +%\let\llcorner\@undefined +%%% +\newcommand{\HolOclWfrec}{\mathop\MathOcl{\operatorname{Wfrec}}} +\endinput diff --git a/document/introduction.tex b/document/introduction.tex new file mode 100644 index 0000000..f91b96b --- /dev/null +++ b/document/introduction.tex @@ -0,0 +1,1490 @@ +\part{Introduction} +\chapter{Motivation} +The Unified Modeling Language +(UML)~\cite{omg:uml-infrastructure:2011,omg:uml-superstructure:2011} +is one of the few modeling languages that is widely used in +industry. UML is defined, in an open process, by the Object Management +Group (OMG), \ie, an industry consortium. While UML is mostly known +as diagrammatic modeling language (\eg, visualizing class models), it +also comprises a textual language, called Object Constraint Language +(OCL)~\cite{omg:ocl:2012}. OCL is a textual annotation language, +originally conceived as a three-valued logic, that turns substantial +parts of UML into a formal language. Unfortunately the semantics of +this specification language, captured in the ``Annex A'' (originally, +based on the work of \citet{richters:precise:2002}) of the OCL +standard leads to different interpretations of corner cases. Many of +these corner cases had been subject to formal analysis since more than +nearly fifteen years (see, +\eg,~\cite{brucker.ea:semantic:2006-b,brucker.ea:proposal:2002,mandel.ea:ocl:1999, + hamie.ea:reflections:1998,cook.ea::amsterdam:2002}). + +At its origins~\cite{richters:precise:2002,omg:ocl:1997}, OCL was +conceived as a strict semantics for undefinedness (\eg, denoted by the +element \inlineocl{invalid}\footnote{In earlier versions of the OCL + standard, this element was called \inlineocl{OclUndefined}.}), with +the exception of the logical connectives of type \inlineocl{Boolean} +that constitute a three-valued propositional logic. At its core, OCL +comprises four layers: +\begin{enumerate} +\item Operators (\eg, \inlineocl{_ and _}, \inlineocl{_ + _}) on + built-in data structures such as \inlineocl{Boolean}, + \inlineocl{Integer}, or typed sets (\inlineocl{Set(_)}. +\item Operators on the user-defined data model (\eg, defined as part + of a UML class model) such as accessors, type casts and tests. +\item Arbitrary, user-defined, side-effect-free methods, +\item Specification for invariants on states and contracts for + operations to be specified via pre- and post-conditions. +\end{enumerate} + +Motivated by the need for aligning OCL closer with UML, recent +versions of the OCL standard~\cite{omg:ocl:2006,omg:ocl:2012} added a +second exception element. While the first exception element +\inlineocl{invalid} has a strict semantics, \inlineocl{null} has a non +strict semantic interpretation. Unfortunately, this extension results +in several inconsistencies and contradictions. These problems are +reflected in difficulties to define interpreters, code-generators, +specification animators or theorem provers for OCL in a uniform manner +and resulting incompatibilities of various tools. + +For the OCL community, the semantics of \inlineocl{invalid} and +\inlineocl{null} as well as many related issues resulted in the +challenge to define a consistent version of the OCL standard that is +well aligned with the recent developments of the UML\@. A syntactical +and semantical consistent standard requires a major revision of both +the informal and formal parts of the standard. To discuss the future +directions of the standard, several OCL experts met in November 2013 +in Aachen to discuss possible mid-term improvements of OCL, strategies +of standardization of OCL within the OMG, and a vision for possible +long-term developments of the +language~\cite{brucker.ea:summary-aachen:2013}. During this meeting, a +Request for Proposals (RFP) for OCL 2.5 was finalized and meanwhile +proposed. In particular, this RFP requires that the future OCL 2.5 +standard document shall be generated from a machine-checked +source. This will ensure +\begin{itemize} +\item the absence of syntax errors, +\item the consistency of the formal semantics, +\item a suite of corner-cases relevant for OCL tool implementors. +\end{itemize} + +In this document, we present a formalization using +Isabelle/HOL~\cite{nipkow.ea:isabelle:2002} of a core language of +OCL\@. The semantic theory, based on a ``shallow embedding'', is +called \emph{Featherweight OCL}, since it focuses on a formal +treatment of the key-elements of the language (rather than a full +treatment of all operators and thus, a ``complete'' +implementation). In contrast to full OCL, it comprises just the logic +captured in \verb+Boolean+, the basic data type \verb+Integer+, the +collection type \verb+Set+, as well as the generic construction +principle of class models, which is instantiated and demonstrated for +two examples (an automated support for this type-safe construction is +again out of the scope of Featherweight OCL). This formal semantics +definition is intended to be a proposal for the standardization +process of OCL 2.5, which should ultimately replace parts of the +mandatory part of the standard document~\cite{omg:ocl:2012} as well as +replace completely its informative ``Annex A.'' + + +\chapter{Background} +\section{A Guided Tour Through UML/OCL} +\label{sec:guidedtour} +The Unified Modeling Language +(UML)~\cite{omg:uml-infrastructure:2011,omg:uml-superstructure:2011} +comprises a variety of model types for describing static (\eg, class +models, object models) and dynamic (\eg, state-machines, activity +graphs) system properties. +\begin{figure*} + \centering\scalebox{1}{\includegraphics{figures/AbstractSimpleChair}}% + \caption{A simple UML class model representing a conference + system for organizing conference sessions: persons can + participate, in different roles, in a session. \label{fig:uml}} +\end{figure*} +One of the more prominent model types of the UML is the +\emph{class model} (visualized as \emph{class diagram}) for modeling +the underlying data model of a system in an object-oriented manner. As +a running example, we model a part of a conference management +system. Such a system usually supports the conference organizing +process, \eg, creating a conference Website, reviewing submissions, +registering attendees, organizing the different sessions and tracks, +and indexing and producing the resulting proceedings. In this example, +we constrain ourselves to the process of organizing conference +sessions; \autoref{fig:uml} shows the class model. We model the +hierarchy of roles of our system as a hierarchy of classes (\eg, +\inlineocl{Hearer}, \inlineocl{Speaker}, or \inlineocl{Chair}) using +an \emph{inheritance} relation (also called \emph{generalization}). In +particular, \emph{inheritance} establishes a \emph{subtyping} +relationship, \ie, every \inlineocl{Speaker} (\emph{subclass}) is also +a \inlineocl{Hearer} (\emph{superclass}). + +A class does not only describe a set of \emph{instances} (called +\emph{objects}), \ie, record-like data consisting of \emph{attributes} +such as \inlineocl{name} of class \inlineocl{Session}, but also +\emph{operations} defined over them. For example, for the class +\inlineocl{Session}, representing a conference session, we model an +operation \inlineocl{findRole(p:Person):Role} that should return the +role of a \inlineocl{Person} in the context of a specific session; +later, we will describe the behavior of this operation in more detail +using UML\@. In the following, the term object describes a +(run-time) instance of a class or one of its subclasses. + +Relations between classes (called \emph{associations} in UML) +can be represented in a class diagram by connecting lines, \eg, +\inlineocl{Participant} and \inlineocl{Session} or \inlineocl{Person} +and \inlineocl{Role}. Associations may be labeled by a particular +constraint called \emph{multiplicity}, \eg, \inlineocl+0..*+ or +\inlineocl+0..1+, which means that in a relation between participants +and sessions, each \inlineocl{Participant} object is associated to at +most one \inlineocl{Session} object, while each \inlineocl{Session} +object may be associated to arbitrarily many \inlineocl{Participant} +objects. Furthermore, associations may be labeled by projection +functions like \inlineocl{person} and \inlineocl{role}; these implicit +function definitions allow for OCL-expressions like +\inlineocl+self.person+, where \inlineocl+self+ is a variable of the +class \inlineocl{Role}. The expression \inlineocl+self.person+ denotes +persons being related to the specific object \inlineocl{self} of +type role. A particular feature of the UML are \emph{association + classes} (\inlineocl{Participant} in our example) which represent a +concrete tuple of the relation within a system state as an object; +\ie, associations classes allow also for defining attributes and +operations for such tuples. In a class diagram, association classes +are represented by a dotted line connecting the class with the +association. Associations classes can take part in other associations. +Moreover, UML supports also $n$-ary associations (not shown in +our example). + +We refine this data model using the Object Constraint Language (OCL) +for specifying additional invariants, preconditions and postconditions +of operations. For example, we specify that objects of the class +\inlineocl{Person} are uniquely determined by the value of the +\inlineocl{name} attribute and that the attribute \inlineocl{name} is +not equal to the empty string (denoted by \inlineocl{''}): +\begin{ocl} +context Person + inv: name <> '' and + Person::allInstances()->isUnique(p:Person | p.name) +\end{ocl} +Moreover, we specify that every session has exactly one chair by the +following invariant (called \inlineocl{onlyOneChair}) of the class +\inlineocl{Session}: +\begin{ocl} +context Session + inv onlyOneChair: self.participants->one( p:Participant | + p.role.oclIsTypeOf(Chair)) +\end{ocl} +where \inlineocl{p.role.oclIsTypeOf(Chair)} evaluates to true, if +\inlineocl{p.role} is of \emph{dynamic type} +\inlineocl{Chair}. Besides the usual \emph{static types} (\ie, the +types inferred by a static type inference), objects in UML and other +object-oriented languages have a second \emph{dynamic} type concept. +This is a consequence of a family of \emph{casting functions} (written +$\typeCast{o}{C}$ for an object $o$ into another class type $C$) that +allows for converting the static type of objects along the class +hierarchy. The dynamic type of an object can be understood as its +``initial static type'' and is unchanged by casts. We complete our +example by describing the behavior of the operation +\inlineocl{findRole} as follows: +\begin{ocl} +context Session::findRole(person:Person):Role + pre: self.participates.person->includes(person) + post: result=self.participants->one(p:Participant | + p.person = person ).role + and self.participants = self.participants@pre + and self.name = self.name@pre +\end{ocl} +where in post-conditions, the operator \inlineocl{@pre} allows for +accessing the previous state. + +In UML, classes can contain attributes of the type of the +defining class. Thus, UML can represent (mutually) recursive +datatypes. Moreover, OCL introduces also recursively specified +operations. + +A key idea of defining the semantics of UML and extensions like +SecureUML~\cite{brucker.ea:transformation:2006} is to translate the +diagrammatic UML features into a combination of more elementary +features of UML and OCL +expressions~\cite{gogolla.ea:expressing:2001}. For example, +associations are usually represented by collection-valued class +attributes together with OCL constraints expressing the +multiplicity. Thus, having a semantics for a subset of UML and OCL is +tantamount for the foundation of the entire method. + + + + + + +\section{Formal Foundation} + + +\subsection{Isabelle} +Isabelle~\cite{nipkow.ea:isabelle:2002} is a \emph{generic} theorem +prover. New object logics can be introduced by specifying their syntax +and natural deduction inference rules. Among other logics, Isabelle +supports first-order logic, Zermelo-Fraenkel set theory and the +instance for Church's higher-order logic (HOL). + +Isabelle's inference rules are based on the built-in meta-level +implication $\_ \Implies \_$ allowing to form constructs like $A_1 +\Implies \cdots \Implies A_n \Implies A_{n+1}$, which are viewed as a +\emph{rule} of the form ``from assumptions $A_1$ to $A_n$, infer +conclusion $A_{n+1}$'' and which is written in Isabelle as +\begin{gather} + \semantics{A_1 ; \ldots; A_n}\Implies A_{n+1} + \qquad + \text{or, in mathematical notation,} + \qquad + \begin{prooftree} + A_1 \qquad \cdots \qquad A_n + \justifies + A_{n+1} + \ptmi{.} + \end{prooftree} +\end{gather} +The built-in meta-level quantification $\Forall x\spot x$ captures +the usual side-constraints ``$x$ must not occur free in the +assumptions'' for quantifier rules; meta-quantified variables can be +considered as ``fresh'' free variables. Meta-level quantification +leads to a generalization of Horn-clauses of the form: +\begin{gather} +\Forall x_1, \ldots, x_m\spot \semantics{A_1 ; \ldots; A_n}\Implies +A_{n+1}\mi{.} +\end{gather} + +Isabelle supports forward- and backward reasoning on rules. For +backward-reasoning, a \emph{proof-state} can be initialized and +further transformed into others. For example, a proof of $\phi$, using +the Isar~\cite{wenzel:isabelleisar:2002} language, will look as +follows in Isabelle: +\begin{gather} + \begin{array}{l} + \Lemma{label} \phi\\ + \quad\apply{case\_tac}\\ + \quad\apply{simp\_all}\\ + \done + \end{array} +\end{gather} +This proof script instructs Isabelle to prove $\phi$ by case +distinction followed by a simplification of the resulting proof state. +Such a proof state is an implicitly conjoint sequence of generalized +Horn-clauses (called \emph{subgoals}) $\phi_1$, \ldots,$\phi_n$ and a +\emph{goal} $\phi$. Proof states were usually denoted by: +\begin{gather} +\begin{array}{rl} +\pglabel{label}:& \phi \\ + 1.& \phi_1 \\ + &\vdots \\ + n.& \phi_n\\ +\end{array} +\end{gather} +Subgoals and goals may be extracted from the proof state into theorems +of the form $\semantics{\phi_1 ; \ldots; \phi_n}\Implies \phi$ at any +time; this mechanism helps to generate test theorems. Further, +Isabelle supports meta-variables (written $\meta{x}, \meta{y}, +\ldots$), which can be seen as ``holes in a term'' that can still be +substituted. Meta-variables are instantiated by Isabelle's built-in +higher-order unification. + +\subsection{Higher-order Logic (HOL)} +\emph{Higher-order logic} +(HOL)~\cite{church:types:1940,andrews:introduction:2002} is a +classical logic based on a simple type system. It provides the usual +logical connectives like $\_ \land \_$, $\_ \implies\_$, $\lnot \_ $ +as well as the object-logical quantifiers $\forall x\spot P\ap x$ and +$\exists x\spot P\ap x$; in contrast to first-order logic, quantifiers +may range over arbitrary types, including total functions +$f\ofType\alpha \Rightarrow \beta$. HOL is centered around +extensional equality $\_ = \_ \ofType \alpha \Rightarrow \alpha +\Rightarrow \text{bool}$. HOL is more expressive than first-order +logic, since, \eg, induction schemes can be expressed inside the +logic. Being based on some polymorphically typed $\lambda$-calculus, +HOL can be viewed as a combination of a programming language +like SML or Haskell and a specification language providing +powerful logical quantifiers ranging over elementary and function +types. + +Isabelle/HOL is a logical embedding of HOL into Isabelle. The +(original) simple-type system underlying HOL has been extended by +Hindley-Milner style polymorphism with type-classes similar to +Haskell. While Isabelle/HOL is usually seen as proof assistant, we +use it as symbolic computation environment. Implementations on top of +Isabelle/HOL can re-use existing powerful deduction mechanisms such as +higher-order resolution, tableaux-based reasoners, rewriting +procedures, Presburger arithmetic, and via various integration +mechanisms, also external provers such as +Vampire~\cite{riazanov.ea:vampire:1999} and the SMT-solver +Z3~\cite{moura.ea:z3:2008}. + +Isabelle/HOL offers support for a particular methodology to extend +given theories in a logically safe way: A theory-extension is +\emph{conservative} if the extended theory is consistent provided that +the original theory was consistent. Conservative extensions can be +\emph{constant definitions}, \emph{type definitions}, \emph{datatype + definitions}, \emph{primitive recursive definitions} and +\emph{wellfounded recursive definitions}. + +For instance, the library includes the type constructor $\up{\tau} := +\isasymbottom ~ | ~ \lift{\_} : \alpha$ that assigns to each type +$\tau$ a type $\up{\tau}$ \emph{disjointly extended} by the +exceptional element $\isasymbottom$. The function $\drop{\_} : +\up{\alpha} \to \alpha$ is the inverse of $\lift{\_}$ (unspecified for +$\isasymbottom$). Partial functions $\alpha \isasymrightharpoonup +\beta$ are defined as functions $\alpha \isasymRightarrow \up{\beta}$ +supporting the usual concepts of domain ($\dom\;\_$) and range +($\ran\;\_$). + +As another example of a conservative extension, typed sets were built +in the Isabelle libraries conservatively on top of the kernel of HOL +as functions to $\HolBoolean$; consequently, the constant definitions +for membership is as follows:\footnote{To increase readability, we use + a slightly simplified presentation.} +\begin{gather} + \begin{array}{lrll} + \types& \alpha \HolSet &= \alpha \Rightarrow \HolBoolean\\[.5ex] + \definitionS &\operatorname{Collect}&\ofType (\alpha \Rightarrow + \HolBoolean) \Rightarrow \HolSet{\alpha} &\qquad\text{--- set comprehension}\\ + \where &\operatorname{Collect}\ap S &\equiv S\\[.5ex] + \definitionS &\operatorname{member} &\ofType \alpha \Rightarrow + \alpha \Rightarrow \HolBoolean &\qquad\text{--- + membership test}\\ + \where &\operatorname{member}\ap s\ap S &\equiv S s\\ + \end{array} +\end{gather} +Isabelle's syntax engine is instructed to accept the notation +$\{x \mid P\}$ for $\operatorname{Collect}\ap\lambda x\spot P$ and the +notation $s \in S$ for $\operatorname{member}\ap s\ap S$. As can be +inferred from the example, constant definitions are axioms that +introduce a fresh constant symbol by some closed, non-recursive +expressions; this type of axiom is logically safe since it works +like an abbreviation. The syntactic side conditions of this axiom are +mechanically checked, of course. It is straightforward to express the +usual operations on sets like $\_ \cup \_, +\_\cap\_\ofType\HolSet{\alpha} \Rightarrow \HolSet{\alpha} \Rightarrow +\HolSet{\alpha}$ as conservative extensions, too, while the rules of +typed set theory were derived by proofs from these definitions. + +Similarly, a logical compiler is invoked for the following statements introducing +the types option and list: +\begin{gather} + \begin{array}{lrll} + \datatype & \HolOption &= \HolNone \mid \HolSome{\alpha}\\[.5ex] + \datatype & \HolList{\alpha} &= \operatorname{Nil} \mid + \operatorname{Cons}\ap a\ap l + \end{array} +\end{gather} +Here, $[]$ or $a\#l$ are an alternative syntax for $\operatorname{Nil}$ +or $\operatorname{Cons}\ap a ~l$; moreover, $[a, b, c]$ is defined as +alternative syntax for $a\#b\#c\#[]$. These (recursive) statements +were internally represented in by internal type and constant +definitions. Besides the \emph{constructors} $\HolNone$, $\HolSome$, +$[]$ and $\operatorname{Cons}$, there is the match operation +\begin{gather} +\HolCase\ap x\ap\HolOf~\HolNone \isasymRightarrow F\ap \mid +\HolSome{a} \isasymRightarrow G\ap a +\end{gather} +respectively +\begin{gather} +\HolCase\ap x\ap\HolOf~[] \isasymRightarrow F\ap \mid \operatorname{Cons}\ap a\ap +r \isasymRightarrow G\ap a\ap r\mi{.} +\end{gather} +From the internal definitions (not shown here) several properties were +automatically derived. We show only the case for lists: +\begin{gather}\label{eq:datatype-rules} + \begin{array}{ll} + (\HolCase\ap[]\ap\HolOf\ap[] \Rightarrow F \ap | \ap (a\#r) \Rightarrow + G\ap a\ap r) = F &\\ + (\HolCase \ap b\#t \ap \HolOf \ap [] \Rightarrow F \ap | \ap + (a\#r) \Rightarrow G\ap a\ap r) = G~b~t &\\ % + \mbox{}[] \neq a\#t &\text{-- distinctness} \\ + \semantics{ a = [] \implies P ; \exists~x~t\spot a = x\#t \implies P } \Longrightarrow P &\text{-- exhaust} \\ + \semantics{ P [] ; \forall~at\spot P t \implies P (a\#t) } \Longrightarrow P x &\text{-- induct} + \end{array} +\end{gather} +Finally, there is a compiler for primitive and wellfounded recursive +function definitions. For example, we may define the +$\operatorname{sort}$ operation of our running test example by: +\begin{gather}\label{eq:sortdef} + \begin{array}{lll} + \fun + &\enspace\operatorname{ins} & \ofType + [\alpha\ofType\mathrm{linorder}, \HolList{\alpha}] + \Rightarrow + \HolList{\alpha}\\ + \where + &\enspace \operatorname{ins}\ap x \ap [\;] &= [x]\\ + &\enspace \operatorname{ins}\ap x \ap (y\#\mathit{ys})&= + \HolIf x < y + \HolThen x\# y \# ys + \HolElse y\#(\operatorname{ins} \ap x \ap ys) + \end{array}\\ + \begin{array}{lll} + \fun + &\enspace\operatorname{sort} & \ofType + \HolList{(\alpha\ofType\mathrm{linorder})} + \Rightarrow + \HolList{\alpha}\\ + \where + &\enspace \operatorname{sort}\ap [\;] &= [\;]\\ + &\enspace \operatorname{sort} (x\#\mathit{xs})&= + \operatorname{ins}\ap x\ap (\operatorname{sort}\ap xs) + \end{array} +\end{gather} +The internal (non-recursive) constant definition for these operations +is quite involved; however, the logical compiler will finally derive +all the equations in the statements above from this definition and +make them available for automated simplification. + +Thus, Isabelle/HOL also provides a large collection of theories like +sets, lists, multisets, orderings, and various arithmetic theories +which only contain rules derived from conservative definitions. In +particular, Isabelle manages a set of \emph{executable types and + operators}, \ie, types and operators for which a compilation to +SML, OCaml or Haskell is possible. Setups for arithmetic types +such as $\text{int}$ have been done; moreover any datatype and any +recursive function were included in this executable set (providing +that they only consist of executable operators). Similarly, Isabelle +manages a large set of (higher-order) rewrite rules into which +recursive function definitions were included. Provided that this +rule set represents a terminating and confluent rewrite system, the +Isabelle simplifier provides also a highly potent decision procedure +for many fragments of theories underlying the constraints to be +processed when constructing test theorems. + +\section{Featherweight OCL: Design Goals} +Featherweight OCL is a formalization of the core of OCL +aiming at formally investigating the relationship between the +various concepts. At present, it does not attempt to define the complete +OCL library. Instead, it concentrates on the core concepts of +OCL as well as the types \inlineocl{Boolean}, +\inlineocl{Integer}, and typed sets (\inlineocl|Set(T)|). Following +the tradition of +HOL-OCL~\cite{brucker.ea:hol-ocl:2008,brucker.ea:hol-ocl-book:2006}, +Featherweight OCL is based on the following principles: +\begin{enumerate} +\item It is an embedding into a powerful semantic meta-language and + environment, namely + Isabelle/HOL~\cite{nipkow.ea:isabelle:2002}. +\item It is a \emph{shallow embedding} in HOL; types + in OCL were injectively mapped to types in Featherweight + OCL\@. Ill-typed OCL specifications cannot be represented in + Featherweight OCL and a type in Featherweight OCL contains exactly + the values that are possible in OCL\@. Thus, sets may contain + \inlineocl{null} (\inlineocl|Set{null}| is a defined set) but not + \inlineocl{invalid} (\inlineocl|Set{invalid}| is just + \inlineocl{invalid}). +\item Any Featherweight OCL type contains at least + \inlineocl{invalid} and \inlineocl{null} (the type \inlineocl{Void} + contains only these instances). The logic is consequently + four-valued, and there is a \inlineocl{null}-element in the type + \inlineocl{Set(A)}. +\item It is a strongly typed language in the Hindley-Milner tradition. + We assume that a pre-process eliminates all implicit conversions due + to subtyping by introducing explicit casts (\eg, + \inlineocl{oclAsType()}). The details of such a pre-processing are + described in~\cite{brucker:interactive:2007}. Casts are semantic + functions, typically injections, that may convert data between the + different Featherweight OCL types. +\item All objects are represented in an object universe in the HOL-OCL + tradition~\cite{brucker.ea:extensible:2008-b}. The universe + construction also gives semantics to type casts, dynamic type + tests, as well as functions such as \inlineocl{oclAllInstances()}, + or \inlineocl{oclIsNew()}. +\item Featherweight OCL types may be arbitrarily nested. For example, + the expression + \inlineocl|Set{Set{1,2}} = Set{Set{2,1}}| is legal and true. +\item For demonstration purposes, the set type in Featherweight OCL + may be infinite, allowing infinite quantification and a constant + that contains the set of all Integers. Arithmetic laws like + commutativity may therefore be expressed in OCL itself. The + iterator is only defined on finite sets. +\item It supports equational reasoning and congruence reasoning, but + this requires a differentiation of the different equalities like + strict equality, strong equality, meta-equality (HOL). Strict + equality and strong equality require a subcalculus, ``cp'' (a + detailed discussion of the different equalities as well as the + subcalculus ``cp''---for three-valued OCL 2.0---is given + in~\cite{brucker.ea:semantics:2009}), which is nasty but can be + hidden from the user inside tools. +\end{enumerate} + +\section{The Theory Organization} +The semantic theory is organized in a quite conventional manner in +three layers. The first layer, called the \emph{denotational + semantics} comprises a set of definitions of the operators of the +language. Presented as \emph{definitional axioms} inside +Isabelle/HOL, this part assures the logically consistency of the +overall construction. The second layer, called \emph{logical layer}, +is derived from the former and centered around the notion of validity +of an OCL formula $P$ for a state-transition from pre-state $\sigma$ +to post-state $\sigma'$, validity statements were written $(\sigma, +\sigma') \models P$. The third layer, called \emph{algebraic layer}, +also derived from the former layers, tries to establish algebraic laws +of the form $P = P'$; such laws are amenable to equational reasoning +and also help for automated reasoning and code-generation. + +For space reasons, we will restrict ourselves in this paper to a few +operators and make a traversal through all three layers to give a +high-level description of our formalization. Especially, the details +of the semantic construction for sets and the handling of objects and +object universes were excluded from a presentation here. + +\subsection{Denotational Semantics} + OCL is composed of + \begin{enumerate} + \item operators on built-in data structures such as + \inlineocl{Boolean}, \inlineocl{Integer}, or \inlineocl{Set(A)}, + \item operators of the user-defined data-model such as accessors, + type-casts and tests, and + \item user-defined, side-effect-free methods. + \end{enumerate} + Conceptually, an OCL expression in general and Boolean expressions in + particular (\ie, \emph{formulae}) depends on the pair $(\sigma, + \sigma')$ of pre-and post-state. The precise form of states is + irrelevant for this paper (compare~\cite{brucker.ea:ocl-null:2009}) + and will be left abstract in this presentation. We construct in + Isabelle a type-class $\TCnull$ that contains two distinguishable + elements $\HolBot$ and $\HolNull$. Any type of the form + $\up{(\up{\alpha})}$ is an instance of this type-class with $\HolBot + \equiv \isasymbottom$ and $\HolNull \equiv \lfloor \isasymbottom \rfloor$. +Now, any OCL type can be represented by an HOL type of the form: +\begin{equation*} + \V{}{\alpha} \defeq \state{} \times \state{} \to \alpha \ofType \TCnull \mi{.} +\end{equation*} +On this basis, we define $\V{}{\up{(\up{\HolBoolean })}}$ as the HOL +type for the OCL type $\mocl{Boolean}$ and define: +\begin{gather*} +\begin{alignedat}{3} +I\semantics{\mocl{invalid}\ofType V(\alpha)} \tau &\equiv \HolBot & +\qquad I\semantics{\mocl{null}\ofType V(\alpha)} \tau &\equiv \HolNull\\ +I\semantics{\mocl{true}\ofType\mocl{Boolean}} \tau &=\lfloor\lfloor +\HolTrue\rfloor\rfloor & +I\semantics{\mocl{false}} \tau &= \lfloor\lfloor\HolFalse\rfloor\rfloor\\ +\end{alignedat}\\ +I\semantics{X\mocl{.oclIsUndefined()}} \tau = + (\HolIf I\semantics{X}\tau \in \{\HolBot, \HolNull\} \HolThen I\semantics{\mocl{true}}\tau \HolElse I\semantics{\mocl{false}}\tau)\\ + I\semantics{X\mocl{.oclIsInvalid()}} \tau = + (\HolIf I\semantics{X}\tau = \HolBot \HolThen I\semantics{\mocl{true}}\tau \HolElse I\semantics{\mocl{false}}\tau) +\end{gather*} +where $I\semantics{E}$ is the semantic interpretation function +commonly used in mathematical textbooks and $\tau$ stands for pairs of +pre- and post state $(\sigma, \sigma')$. For reasons of conciseness, +we will write $\delta~X$ for $\mocl{not}\;X\mocl{.oclIsUndefined()}$ +and $\upsilon~X$ for $\mocl{not}\;X\mocl{.oclIsInvalid()}$ throughout +this paper. + +Due to the used style of +semantic representation (a shallow embedding) $I$ is in fact +superfluous and defined semantically as the identity; instead of: +\begin{gather*} +I\semantics{\mocl{true}\ofType\mocl{Boolean}} \tau =\lfloor\lfloor \HolTrue\rfloor\rfloor +\shortintertext{we can therefore write:} +\mocl{true}\ofType\mocl{Boolean} = \lambda \tau. \lfloor\lfloor +\HolTrue\rfloor\rfloor +\end{gather*} +In Isabelle theories, this particular presentation of definitions +paves the way for an automatic check that the underlying equation +has the form of an \emph{axiomatic +definition} and is therefore logically safe. +Since all operators of the assertion language depend on the context $\tau$ = $(\sigma, +\sigma')$ and result in values that can be $\isasymbottom$, all expressions can +be viewed as \emph{evaluations} from $(\sigma, \sigma')$ to a type $\alpha$ +which must posses a $\bottom$ and a $\text{null}$-element. Given that such +constraints can be expressed in Isabelle/HOL via \emph{type classes} (written: $\alpha::\kappa$), +all types for OCL-expressions are of a form captured by + \begin{equation*} + \V{}{\alpha} \defeq \state{} \times \state{} \to \alpha::\{bot,null\} \mi{,} + \end{equation*} +where $\state{}$ stands for the system state and $\state{} \times +\state{}$ describes the pair of pre-state and post-state and +$\_\defeq\_$ denotes the type abbreviation. + +The current OCL semantics~\cite[Annex A]{omg:ocl:2003} uses different +interpretation functions for invariants and pre-conditions; we achieve +their semantic effect by a syntactic transformation $\__\text{pre}$ +which replaces, for example, all accessor functions +$\getAttrib{\_}{a}$ by their counterparts +$\getAttrib{\_}{a\isasymOclATpre}$. For example, +$(\getAttrib{\self}{a} > 5)_\text{pre}$ is just +$(\getAttrib{\self}{a\isasymOclATpre} > 5)$. This way, also invariants +and pre-conditions can be interpreted by the same interpretation +function and have the same type of an evaluation $\V{}{\alpha}$. + + +On this basis, one can define the core logical operators $\mocl{not}$ +and $\mocl{and}$ as follows: +\begin{gather*} + \begin{array}{ll} + I\semantics{\mocl{not}\; X} \tau + &= (\HolCase I\semantics{X} \tau \HolOf\\ + &\quad\begin{array}{ll} + ~ \bottom &\Rightarrow \bottom \\ + | \lfloor \bottom \rfloor &\Rightarrow \lfloor \bottom \rfloor \\ + | \lfloor \lfloor x \rfloor \rfloor &\Rightarrow \lfloor \lfloor \lnot x \rfloor \rfloor ) + \end{array} + \end{array} +\end{gather*} + +\begin{gather*} + \begin{array}{ll} + I\semantics{X\;\mocl{and}\; Y} \tau + &= (\HolCase I\semantics{X} \tau \HolOf\\ + &\quad\begin{array}{ll} + ~ \bottom &\Rightarrow + (\HolCase I\semantics{Y} \tau \HolOf\\ + &\quad\begin{array}{ll} + ~ \bottom &\Rightarrow \bottom \\ + | \lfloor \bottom \rfloor &\Rightarrow \bottom \\ + | \lfloor \lfloor \HolTrue \rfloor \rfloor + &\Rightarrow \bottom\\ + | \lfloor \lfloor \HolFalse \rfloor \rfloor + &\Rightarrow \lfloor \lfloor \HolFalse \rfloor \rfloor )\\ + \end{array} + \\ + | \lfloor \bottom \rfloor &\Rightarrow + (\HolCase I\semantics{Y} \tau \HolOf\\ + &\quad\begin{array}{ll} + ~ \bottom &\Rightarrow + \bottom \\ + | \lfloor \bottom \rfloor &\Rightarrow \lfloor + \bottom \rfloor \\ + | \lfloor \lfloor \HolTrue \rfloor \rfloor + &\Rightarrow \lfloor \bottom\rfloor\\ + | \lfloor \lfloor \HolFalse \rfloor \rfloor + &\Rightarrow \lfloor \lfloor \HolFalse \rfloor \rfloor )\\ + \end{array} + \\ + | \lfloor \lfloor \HolTrue \rfloor \rfloor &\Rightarrow + (\HolCase I\semantics{Y} \tau \HolOf\\ + &\quad\begin{array}{ll} + ~ \bottom &\Rightarrow + \bottom \\ + | \lfloor \bottom \rfloor &\Rightarrow \lfloor + \bottom \rfloor \\ + | \lfloor \lfloor y \rfloor \rfloor + &\Rightarrow \lfloor \lfloor y \rfloor \rfloor )\\ + \end{array} + \\ + | \lfloor \lfloor \HolFalse \rfloor \rfloor + &\Rightarrow \lfloor \lfloor \HolFalse \rfloor + \rfloor )\\ + \end{array}\\ +\end{array} +\end{gather*} +These non-strict operations were used to define the other logical connectives in the +usual classical way: $X\; \mocl{or}\; Y \equiv (\mocl{not}\; X)\; +\mocl{and}\; (\mocl{not}\; Y)$ or +$X\;\mocl{implies}\;Y \equiv (\mocl{not}\; X)\;\mocl{or}\; Y$. + +The default semantics for an OCL library operator is strict +semantics; this means that the result of an operation $f$ is +\inlineisar+invalid+ if one of its arguments is \inlineisar+invalid+. +For a semantics comprising \inlineisar+null+, we suggest to stay +conform to the standard and define the addition for integers as +follows: + \begin{gather*} + \begin{array}{rl} + I\semantics{x \;\mocl{+}\; y}\tau = &\HolIf I\semantics{\delta ~ x}\tau =\lfloor \lfloor \HolTrue\rfloor \rfloor \land I\semantics{\delta ~ y}\tau =\lfloor \lfloor \HolTrue\rfloor \rfloor \\ + &\HolThen \lfloor \lfloor \lceil \lceil I\semantics{x}\tau \rceil \rceil + \lceil \lceil I\semantics{y}\tau \rceil \rceil \rfloor \rfloor\\ + &\HolElse \bottom + \end{array} + \end{gather*} + where the operator ``\mocl{+}'' on the left-hand + side of the equation denotes the OCL addition of type + $[\V{}{\up{(\up{\HolInteger})}}, \V{}{\up{(\up{\HolInteger})}}] \Rightarrow + \V{}{\up{(\up{\HolInteger})}}$ while the ``$+$'' on the right-hand side of + the equation of type $[\HolInteger,\HolInteger]\Rightarrow + \HolInteger$ denotes the integer-addition from the HOL library. + +\subsection{Logical Layer} +The topmost goal of the logic for OCL is to define the \emph{validity statement}: +\begin{equation*} + (\sigma, \sigma') \isasymMathOclValid P\mi{,} +\end{equation*} +where $\sigma$ is the pre-state and $\sigma'$ the post-state of the +underlying system and $P$ is a formula. +Informally, a formula $P$ is valid if and only if its evaluation in +$(\sigma, \sigma')$ (\ie, $\tau$ for short) yields true. Formally this means: +\begin{equation*} +\tau \isasymMathOclValid P \equiv \bigl(I\semantics{P} \tau = \lfloor \lfloor \HolTrue \rfloor \rfloor \bigr)\mi{.} +\end{equation*} +On this basis, classical, two-valued inference rules can be established for +reasoning over the logical connective, the different notions of equality, +definedness and validity. Generally speaking, rules over logical validity can +relate bits and pieces in various OCL terms and allow---via strong +logical equality discussed below---the replacement +of semantically equivalent sub-expressions. The core inference rules are: +\begin{gather*} +\begin{array}{lccr} + \tau \models \mocl{true} &\quad + \lnot(\tau \models \mocl{false})&\quad + \lnot(\tau \models \mocl{invalid})&\quad + \lnot(\tau \models \mocl{null}) +\end{array}\\ + \tau \models \mocl{not}\; P \Longrightarrow \lnot (\tau \models P)\\ +\begin{array}{lcr} + \tau \models P \;\mocl{and}\; Q \Longrightarrow \tau \models P&\qquad& + \tau \models P \;\mocl{and}\; Q \Longrightarrow \tau \models Q +\end{array}\\ + \tau \models P \Longrightarrow + (\mocl{if}\; P \;\mocl{then}\; B_1 \;\mocl{else}\; B_2 \;\mocl{endif})\tau = B_1\ap \tau\\ + \tau \models \mocl{not}\; P \Longrightarrow + (\mocl{if}\; P \;\mocl{then}\; B_1 \;\mocl{else}\; B_2 \;\mocl{endif})\tau = B_2\ap \tau\\ +\begin{array}[lcr]{lcr} + \tau \models P \Longrightarrow \tau \models \delta \ap P &\qquad& + \tau \models \delta \ap X \Longrightarrow \tau \models \upsilon \ap X +\end{array} +\end{gather*} +By the latter two properties it can be inferred that any valid +property $P$ (so for example: a valid invariant) is defined, which +allows to infer for terms composed by strict operations that their +arguments and finally the variables occurring in it are valid or +defined. + +We propose to distinguish the \emph{strong logical equality} (written +$\_ \isasymMathOclStrongEq \_$), which follows the general principle +that ``equals can be replaced by equals,'' from the \emph{strict + referential equality} (written $\_ \isasymMathOclStrictEq \_$), +which is an object-oriented concept that attempts to approximate and +to implement the former. Strict referential equality, which is the +default in the OCL language and is written \inlineocl|_ = _| +in the standard, is an overloaded concept and has to be defined for +each OCL type individually; for objects resulting from class +definitions, it is implemented by comparing the references to +the objects. In contrast, strong logical equality is a polymorphic +concept which is defined once and for all by: +\begin{gather*} + I\semantics{X \triangleq Y} \tau \equiv \lfloor \lfloor + I\semantics{X} \tau= + I\semantics{Y} \tau \rfloor \rfloor +\shortintertext{It enjoys nearly the laws of a congruence:} +\tau \models (x \triangleq x)\\ +\tau \models (x \triangleq y) \Longrightarrow \tau \models (y \triangleq x)\\ +\tau \models (x \triangleq y) \Longrightarrow \tau \models (y \triangleq z) \Longrightarrow \tau \models (x \triangleq z)\\ +\HolOclCp P \Longrightarrow \tau \models (x \triangleq y) \Longrightarrow \tau \models (P\ap x) \Longrightarrow \tau \models (P\ap y) +\end{gather*} +where the predicate $\HolOclCp$ stands for \emph{context-passing}, a +property that is characterized by $P(X)$ equals $\lambda \tau\spot +P(\lambda \_\spot X \tau) \tau$. It means that the state tuple $\tau = +(\sigma, \sigma')$ is passed unchanged from surrounding expressions to +sub-expressions. it is true for all pure OCL expressions (but not +arbitrary mixtures of OCL and HOL) in Featherweight OCL\@. The +necessary side-calculus for establishing $\HolOclCp$ can be fully +automated. + +The logical layer of the Featherweight OCL rules gives also a means +to convert an OCL formula living in its four-valued world into a +representation that is classically two-valued and can be processed by +standard SMT solvers such as CVC3~\cite{barrett.ea:cvc3:2007} or +Z3~\cite{moura.ea:z3:2008}. $\delta$-closure rules for all logical +connectives have the following format, \eg: +\begin{gather*} +\tau \models \delta \ap x \Longrightarrow (\tau \models \ap\mocl{not}\ap x) = (\lnot (\tau \models x))\\ +\tau \models \delta \ap x \Longrightarrow \tau \models \delta \ap y \Longrightarrow (\tau \models x \ap\mocl{and}\ap y) = ( \tau \models x \land \tau \models y)\\ +\begin{multlined} +\tau \models \delta \ap x \Longrightarrow \tau \models \delta \ap y \\ +\Longrightarrow (\tau \models (x \ap\mocl{implies}\ap y)) = ( (\tau \models x) \longrightarrow (\tau \models y)) +\end{multlined} +\end{gather*} +Together with the general case-distinction +\begin{gather*} + \tau \models \delta \ap x \lor \tau \models x \triangleq \mocl{invalid} \lor \tau \models x \triangleq \mocl{null} \mi{,} +\end{gather*} +which is possible for any OCL type, a case distinction on the +variables in a formula can be performed; due to strictness rules, +formulae containing somewhere a variable $x$ that is known to be +$\mocl{invalid}$ or $\mocl{null}$ reduce usually quickly to +contradictions. For example, we can infer from an invariant $\tau +\models x \isasymMathOclStrictEq y \;\mocl{-}\; \mocl{3}$ that we have $\tau +\models x \isasymMathOclStrictEq y \;\mocl{-}\; \mocl{3} \land \tau \models +\delta \ap x \land \tau \models \delta \ap y$. We call the latter formula the +$\delta$-closure of the former. Now, we can convert a formula like +$\tau \models x \;\mocl{>}\; \mocl{0} \ap\mocl{or}\ap \mocl{3} \;\mocl{*}\; y \;\mocl{>}\; +x \;\mocl{*}\; x$ into the equivalent formula +$\tau \models x \;\mocl{>}\; \mocl{0} \lor \tau +\models \mocl{3} \;\mocl{*}\; y \;\mocl{>}\; x \;\mocl{*}\; x$ and thus internalize the +OCL-logic into a classical (and more tool-conform) logic. This +works---for the price of a potential, but due to the usually ``rich'' +$\delta$-closures of invariants rare---exponential blow-up of the +formula for all OCL formulas. + +\subsection{Algebraic Layer} +Based on the logical layer, we build a system with simpler rules which +are amenable to automated reasoning. We restrict ourselves to pure +equations on OCL expressions, where the used equality is the +meta-(HOL-)equality. + +Our denotational definitions on \inlineocl+not+ and \inlineocl+and+ +can be re-formulated in the following ground equations: +\begin{gather*} + \begin{aligned} + \upsilon\; \mocl{invalid} &= \mocl{false}&\qquad + \upsilon\; \mocl{null} &= \mocl{true}\\ + \upsilon\; \mocl{true} &= \mocl{true}&\qquad + \upsilon\; \mocl{false} &= \mocl{true}\\ +\end{aligned}\\[.04\baselineskip] +\begin{aligned} + % + \delta\; \mocl{invalid} &= \mocl{false}&\qquad + \delta\; \mocl{null} &= \mocl{false}\\ + \delta\; \mocl{true} &= \mocl{true}&\qquad + \delta\; \mocl{false} &= \mocl{true}\\ +\end{aligned}\\[.04\baselineskip] +\begin{aligned} + % + \mocl{not}\; \mocl{invalid} &= \mocl{invalid}&\qquad + \mocl{not}\; \mocl{null} &= \mocl{null}\\ + \mocl{not}\; \mocl{true} &= \mocl{false}&\qquad + \mocl{not}\; \mocl{false} &= \mocl{true}\\ +\end{aligned}\\[.04\baselineskip] +\begin{aligned} + % + (\mocl{null} \;\mocl{and}\; \mocl{true}) &= \mocl{null}&\qquad + (\mocl{null} \;\mocl{and}\; \mocl{false}) &= \mocl{false}\\ + (\mocl{null} \;\mocl{and}\; \mocl{null}) &= \mocl{null}&\qquad + (\mocl{null} \;\mocl{and}\; \mocl{invalid}) &= \mocl{invalid}\\ +\end{aligned}\\[.04\baselineskip] +\begin{aligned} + % + (\mocl{false} \;\mocl{and}\; \mocl{true}) &= \mocl{false}&\qquad + (\mocl{false} \;\mocl{and}\; \mocl{false}) &= \mocl{false}\\ + (\mocl{false} \;\mocl{and}\; \mocl{null}) &= \mocl{false}&\qquad + (\mocl{false} \;\mocl{and}\; \mocl{invalid}) &= \mocl{false}\\ +\end{aligned}\\[.04\baselineskip] +\begin{aligned} + % + (\mocl{true} \;\mocl{and}\; \mocl{true}) &= \mocl{true}&\qquad + (\mocl{true} \;\mocl{and}\; \mocl{false}) &= \mocl{false}\\ + (\mocl{true} \;\mocl{and}\; \mocl{null}) &= \mocl{null}&\qquad + (\mocl{true} \;\mocl{and}\; \mocl{invalid}) &= \mocl{invalid} +\end{aligned}\\[.04\baselineskip] +\begin{aligned} + (\mocl{invalid} \;\mocl{and}\; \mocl{true}) &= \mocl{invalid} \\ + (\mocl{invalid} \;\mocl{and}\; \mocl{false}) &= \mocl{false}\\ + (\mocl{invalid} \;\mocl{and}\; \mocl{null}) &= \mocl{invalid} \\ + (\mocl{invalid} \;\mocl{and}\; \mocl{invalid}) &= \mocl{invalid}\\ +\end{aligned} +\shortintertext{On this core, the structure of a conventional lattice arises:} + \begin{aligned} + X \;\mocl{and}\; X &= X &\qquad X \;\mocl{and}\; Y &= Y \;\mocl{and}\; X + \end{aligned}\\ + \begin{aligned} + \mocl{false} \;\mocl{and}\; X &= \mocl{false} &\qquad + X \;\mocl{and}\; \mocl{false} &= \mocl{false} \\ + \mocl{true} \;\mocl{and}\; X &= X &\qquad + X \;\mocl{and}\; \mocl{true} &= X + \end{aligned}\\ + \begin{aligned} + X \;\mocl{and}\; (Y \;\mocl{and}\; Z) &= X \;\mocl{and}\; Y \;\mocl{and}\; Z + \end{aligned} +\end{gather*} +as well as the dual equalities for \inlineocl|_ or _| and the De Morgan +rules. This wealth of algebraic properties makes the understanding of +the logic easier as well as automated analysis possible: it allows +for, for example, computing a DNF of invariant systems (by +clever term-rewriting techniques) which are a prerequisite for +$\delta$-closures. + +The above equations explain the behavior for the most-important +non-strict operations. The clarification of the exceptional behaviors +is of key-importance for a semantic definition the standard and the +major deviation point from +HOL-OCL~\cite{brucker.ea:hol-ocl:2008,brucker.ea:hol-ocl-book:2006}, +to Featherweight OCL as presented here. The +standard expresses at many places that most operations are strict, +\ie, enjoy the properties (exemplary for \inlineocl{_ + _}): +\begin{gather*} + \begin{aligned} + \mocl{invalid}\;\mocl{+}\; X &= \mocl{invalid}&\qquad + X \;\mocl{+}\; \mocl{invalid} &= \mocl{invalid}\\ + X \;\mocl{+}\; \mocl{null} &= \mocl{invalid}&\qquad + \mocl{null} \;\mocl{+}\; X &= \mocl{invalid} + \end{aligned}\\ + \mocl{null.oclAsType(}X\mocl{)} = \mocl{invalid} +\shortintertext{besides ``classical'' exceptional behavior:} + \begin{aligned} + \mocl{1} \;\mocl{/}\; \mocl{0} &= \mocl{invalid} \quad &\quad + \mocl{1} \;\mocl{/}\; \mocl{null} &= \mocl{invalid} + \end{aligned}\\ + \mocl{null->isEmpty()}=\mocl{true} +\end{gather*} + +Moreover, there is also the proposal to use \inlineocl+null+ as a kind +of ``don't know'' value for all strict operations, not only in the +semantics of the logical connectives. Expressed in algebraic +equations, this semantic alternative (this is \emph{not} +Featherweight OCL at present) would boil down to: +\begin{gather*} + \begin{aligned} + \mocl{invalid} \;\mocl{+}\; X &= \mocl{invalid} &\qquad + X \;\mocl{+}\; \mocl{invalid} &= \mocl{invalid}\\ + X \;\mocl{+}\; \mocl{null} &= \mocl{null}&\qquad + \mocl{null} \;\mocl{+}\; X &= \mocl{null} + \end{aligned}\\ + \mocl{null.oclAsType(}X\mocl{)} = \mocl{null}\\ + \begin{aligned} + \mocl{1} \;\mocl{/}\; \mocl{0} &= \mocl{invalid} \quad &\quad + \mocl{1} \;\mocl{/}\; \mocl{null} &= \mocl{null} + \end{aligned}\\ + \mocl{null->isEmpty()}=\mocl{null} +\end{gather*} + +While this is logically perfectly possible, while it can be argued +that this semantics is ``intuitive'', and although we do not expect a +too heavy cost in deduction when computing $\delta$-closures, we +object that there are other, also ``intuitive'' interpretations that +are even more wide-spread: In classical spreadsheet programs, for +example, the semantics tends to interpret \inlineocl+null+ +(representing empty cells in a sheet) as the neutral element of the +type, so \inlineocl{0} or the empty string, for example.\footnote{In + spreadsheet programs the interpretation of \inlineisar+null+ varies + from operation to operation; \eg, the \inlineocl+average+ + function treats \inlineocl+null+ as non-existing value and not as + \inlineocl{0}.} This semantic alternative (this is +\emph{not} Featherweight OCL at present) would yield: +\begin{gather*} + \begin{aligned} + \mocl{invalid} \;\mocl{+}\; X &= \mocl{invalid} &\qquad + X \;\mocl{+}\; \mocl{invalid} &= \mocl{invalid}\\ + X \;\mocl{+}\; \mocl{null} &= X&\qquad + \mocl{null} \;\mocl{+}\; X &= X + \end{aligned}\\ + \mocl{null.oclAsType(}X\mocl{)} = \mocl{invalid}\\ + \begin{aligned} + \mocl{1} \;\mocl{/}\; \mocl{0} &= \mocl{invalid} \quad &\quad + \mocl{1} \;\mocl{/}\; \mocl{null} &= \mocl{invalid} +\end{aligned}\\ + \mocl{null->isEmpty()}=\mocl{true} +\end{gather*} + +Algebraic rules are also the key for execution and compilation +of Featherweight OCL expressions. We derived, \eg: +\begin{gather*} +\delta\; \mocl{Set\{\}} = \mocl{true}\\ +\delta\; (X\mocl{->including(}x\mocl{)}) = \delta \ap X \;\mocl{and}\; +\delta \ap x\\ +\begin{aligned} +\mocl{Set\{\}->includes(}x\mocl{)} = (\mocl{if}\; \upsilon\; x\; &\mocl{then false}\\ +&\mocl{else invalid endif}) +\end{aligned}\\ +\begin{multlined} + {(X\mocl{->including(}x\mocl{)->includes(}y\mocl{)})=}\\ + \mbox{\hspace{3.2cm}}\qquad{\begin{aligned} + (&\mocl{if}\; \delta\; X\\ + &\mocl{then}\; +\begin{array}[t]{l} +\mocl{if}\; x \doteq y\\ +\mocl{then}\ap \mocl{true} \\ +\mocl{else}\ap X\mocl{->includes(}y\mocl{)}\\ +\mocl{endif} + \end{array}\\ +&\mocl{else invalid} \\ + &\mocl{endif}) + \end{aligned}} +\end{multlined} +\end{gather*} +As \inlineocl+Set{1,2}+ is only syntactic sugar for +\begin{ocl} + Set{}->including(1)->including(2) +\end{ocl} +an expression like \inlineocl+Set{1,2}->includes(null)+ becomes +decidable in Featherweight OCL by a combination of +rewriting and code-generation and execution. The generated +documentation from the theory files can thus be enriched by numerous +``test-statements'' like: +\begin{isar}[mathescape] +value "\ \ ($\mathtt{Set\{Set\{2,null\}\}}$ \ $\;\mathtt{Set\{Set\{null,2\}\}}$)" +\end{isar} +which have been machine-checked and which present a high-level and in +our opinion fairly readable information for OCL tool manufactures and +users. + + +\section{Object-oriented Datatype Theories} +As mentioned earlier, the OCL is composed of +\begin{enumerate} +\item operators on built-in data structures such as Boolean, Integer or Set(\_), + and +\item operators of the user-defined data model such as accessors, + type casts and tests. +\end{enumerate} + +In the following, we will refine the concepts of a user-defined +data-model (implied by a \emph{class-model}, visualized by a class-diagram) +as well as the notion of $\state{}$ used in the +previous section to much more detail. In contrast to wide-spread +opinions, UML class diagrams represent in a compact and visual manner +quite complex, object-oriented data-types with a surprisingly rich +theory. It is part of our endeavor here to make this theory explicit +and to point out corner cases. A UML class diagram---underlying a +given OCL formula---produces several implicit operations which +become accessible via appropriate OCL syntax: + +\begin{enumerate} +\item Classes and class names (written as $C_1$, \ldots, $C_n$), which + become types of data in OCL\@. Class names declare two projector + functions to the set of all objects in a state: + $C_i$\inlineocl{.allInstances()} and + $C_i$\inlineocl{.allInstances}$\isasymOclATpre$\inlineocl{()}, +\item an inheritance relation $\_ < \_$ on classes and a collection of + attributes $A$ associated to classes, +\item two families of accessors; for each attribute $a$ in a + class definition (denoted + $\getAttrib{X}{\text{$a$}} :: C_i \rightarrow A $ and + $\getAttrib{X}{\text{$a$}\isasymOclATpre}:: C_i \rightarrow A $ for + $A\in \{\V{}{\up{\ldots}}, C_1, \ldots, C_n\}$), +\item type casts that can change the static type of an object of a + class ($\getAttrib{X}{\mocl{oclAsType(}\text{$C_i$}\mocl{)}}$ of type + $C_j \rightarrow C_i$) +\item two dynamic type tests ($\getAttrib{X}{\mocl{oclIsTypeOf(}\text{$C_i$}\mocl{)}}$ and + $\getAttrib{X}{\mocl{oclIsKindOf(}\text{$C_i$}\mocl{)}}$ ), +\item and last but not least, for each class name $C_i$ there is an + instance of the overloaded referential equality (written $\_ + \isasymMathOclStrictEq \_$). +\end{enumerate} + + +Assuming a strong static type discipline in the sense of +Hindley-Milner types, Featherweight OCL has no ``syntactic +subtyping.'' This does not mean that subtyping cannot be expressed +\emph{semantically} in Featherweight OCL; by giving a formal semantics +to type-casts, subtyping becomes an issue of the front-end that can +make implicit type-coersions explicit by introducing explicit +type-casts. Our perspective shifts the emphasis on the semantic +properties of casting, and the necessary universe of object +representations (induced by a class model) that allows to establish +them. + + +\subsection{Object Universes} + +It is natural to construct system states by a set of partial functions +$f$ that map object identifiers $\oid$ to some representations of +objects: +\begin{gather} + \typedef \qquad \alpha~\state{} \defeq \{ \sigma :: + \oid \isasymrightharpoonup \alpha \ap|\ap \inv_\sigma(\sigma) \} +\end{gather} +where $\inv_\sigma$ is a to be discussed invariant on states. + +The key point is that we need a common type $\alpha$ for the set of all +possible \emph{object representations}. Object representations model +``a piece of typed memory,'' \ie, a kind of record comprising +administration information and the information for all attributes of +an object; here, the primitive types as well as collections over them +are stored directly in the object representations, class types and +collections over them are represented by $\oid$'s (respectively lifted +collections over them). + +In a shallow embedding which must represent +UML types injectively by HOL types, there are two fundamentally +different ways to construct such a set of object representations, +which we call an \emph{object universe} $\mathfrak{A}$: +\begin{enumerate} +\item an object universe can be constructed for a given class model, + leading to \emph{closed world semantics}, and +\item an object universe can be constructed for a given class model + \emph{and all its extensions by new classes added into the leaves of + the class hierarchy}, leading to an \emph{open world semantics}. +\end{enumerate} +For the sake of simplicity, we chose the first option for +Featherweight OCL, while HOL-OCL~\cite{brucker.ea:extensible:2008-b} +used an involved construction allowing the latter. + +A na\"ive attempt to construct $\mathfrak{A}$ would look like this: +the class type $C_i$ induced by a class will be the type of such an +object representation: $C_i \defeq (\oid \times A_{i_1} \times \cdots +\times A_{i_k} )$ where the types $A_{i_1}$, \ldots, $A_{i_k}$ are the +attribute types (including inherited attributes) with class types +substituted by $\oid$. The function $\HolOclOidOf$ projects the first +component, the $\oid$, out of an object representation. Then the +object universe will be constructed by the type definition: +\begin{gather} +\mathfrak{A} := C_1 + \cdots + C_n\mi{.} +\end{gather} +It is possible to define constructors, accessors, and the referential +equality on this object universe. However, the treatment of type casts +and type tests cannot be faithful with common object-oriented +semantics, be it in UML or Java: casting up along the class hierarchy +can only be implemented by loosing information, such that casting up +and casting down will \emph{not} give the required identity: + +\begin{gather} + X.\mocl{oclIsTypeOf(}C_k\mocl{)} ~ ~ \mocl{implies} ~ ~ X\mocl{.oclAsType(}C_i\mocl{)}\mocl{.oclAsType(}C_k\mocl{)} \isasymMathOclStrictEq + X \\ + \qquad \qquad \qquad \qquad \qquad \qquad \text{whenever $C_k < C_i$ and $X$ is valid.} +\end{gather} + + +To overcome this limitation, we introduce an auxiliary type +$C_{i\text{ext}}$ for \emph{class type extension}; together, they were +inductively defined for a given class diagram: + +Let $C_i$ be a class with a possibly empty set of subclasses +$\{C_{j_{1}}, \ldots, C_{j_{m}}\}$. +\begin{itemize} +\item Then the \emph{class type extension} $C_{i\text{ext}}$ + associated to $C_i$ is + $A_{i_{1}} \times \cdots \times A_{i_{n}} \times \up{(C_{j_{1}\text{ext}} + \cdots + C_{j_{m}\text{ext}})}$ + where $A_{i_{k}}$ ranges over the local + attribute types of $C_i$ and $C_{j_{l}\text{ext}}$ + ranges over all class type extensions of the subclass $C_{j}$ of $C_i$. +\item Then the \emph{class type} for $C_i$ is + $oid \times A_{i_{1}} \times \cdots \times A_{i_{n}} \times \up{(C_{j_{1}\text{ext}} + \cdots + C_{j_{m}\text{ext}})}$ + where $A_{i_{k}}$ ranges over the inherited \emph{and} local + attribute types of $C_i$ and $C_{j_{l}\text{ext}}$ + ranges over all class type extensions of the subclass $C_{j}$ of $C_i$. +\end{itemize} + +Example instances of this scheme---outlining a compiler---can be found +in \autoref{ex:employee-analysis:uml} and \autoref{ex:employee-design:uml}. + +This construction can \emph{not} be done in HOL itself since it +involves quantifications and iterations over the ``set of class-types''; +rather, it is a meta-level construction. Technically, this means that +we need a compiler to be done in SML on the syntactic +``meta-model''-level of a class model. + +With respect to our semantic construction here, +which above all means is intended to be type-safe, this has the following consequences: +\begin{itemize} +\item there is a generic theory of states, which must be formulated independently + from a concrete object universe, +\item there is a principle of translation (captured by the inductive scheme for + class type extensions and class types above) that converts a given class model + into an concrete object universe, +\item there are fixed principles that allow to derive the semantic theory of any + concrete object universe, called the \emph{object-oriented datatype theory.} +\end{itemize} +We will work out concrete examples for the construction of the +object-universes in \autoref{ex:employee-analysis:uml} and \autoref{ex:employee-design:uml} and the +derivation of the respective datatype theories. While an +automatization is clearly possible and desirable for concrete +applications of Featherweight OCL, we consider this out of the scope +of this paper which has a focus on the semantic construction and its +presentation. + + +\subsection{Accessors on Objects and Associations} +Our choice to use a shallow embedding of OCL in HOL and, thus having +an injective mapping from OCL types to HOL types, results in +type-safety of Featherweight OCL\@. Arguments and results of accessors +are based on type-safe object representations and \emph{not} $\oid$'s. +This implies the following scheme for an accessor: +\begin{itemize} +\item The \emph{evaluation and extraction} phase. If the argument + evaluation results in an object representation, the $\oid$ is + extracted, if not, exceptional cases like \inlineocl{invalid} are + reported. +\item The \emph{dereferentiation} phase. The $\oid$ is interpreted in + the pre- or post-state, %(depending on the suffix of accessor), + the resulting object is casted to the expected format. The + exceptional case of nonexistence in this state must be treated. +\item The \emph{selection} phase. The corresponding attribute is + extracted from the object representation. +\item The \emph{re-construction} phase. The resulting value has to be + embedded in the adequate HOL type. If an attribute has the type of + an object (not value), it is represented by an optional (set of) + $\oid$, which must be converted via dereferentiation in one of the + states to produce an object representation again. The + exceptional case of nonexistence in this state must be treated. +\end{itemize} + +The first phase directly translates into the following formalization: +\begin{multline} + \shoveleft{\definitionS}\quad\\ + \begin{array}{rllr} + \operatorname{eval\_extract} X\ap f = (\lambda \tau\spot \HolCase + X\ap + \tau \HolOf & \bottom &\Rightarrow + \mocl{invalid}\ap\tau&\text{exception}\\ + |& \lift{\bottom} &\Rightarrow + \mocl{invalid}\ap\tau&\text{deref. null}\\ + |& \lift{\lift{\mathit{obj}}} &\Rightarrow f\ap (\operatorname{oid\_of} \ap \mathit{obj})\ap\tau)& + \end{array} +\end{multline} + +For each class $C$, we introduce the dereferentiation phase of this +form: +\begin{multline} + \definitionS \ap + \operatorname{deref\_oid}_C \ap \mathit{fst\_snd}\ap f\ap \mathit{oid} = + (\lambda \tau\spot \HolCase\ap (\operatorname{heap}\ap + (\mathit{fst\_snd}\ap \tau))\ap \mathit{oid}\ap + \HolOf\\ + \begin{array}{ll} + \phantom{|}\ap \lift{\operatorname{in}_C obj} &\Rightarrow f\ap + \mathit{obj} \ap \tau\\ + |\ap \_ &\Rightarrow \mocl{invalid}\ap \tau) + \end{array} + \end{multline} + +The operation yields undefined if the $\oid$ is uninterpretable in the +state or referencing an object representation not conforming to the +expected type. + +We turn to the selection phase: for each class $C$ in the class model +with at least one attribute, +and each attribute $a$ in this class, +we introduce the selection phase of this form: +\begin{gather} + \begin{array}{rlcll} + \definitionS \ap + \operatorname{select}_a \ap f = (\lambda & + \operatorname{mk}_C \ap oid & \cdots \bottom \cdots & C_{X\text{ext}} & \Rightarrow \mocl{null}\\ + |& \operatorname{mk}_C \ap oid & \cdots \lift{a} \cdots & C_{X\text{ext}} + &\Rightarrow f\ap (\lambda \ap x \ap \_\spot + \lift{\lift{x}})\ap a) + \end{array} +\end{gather} + +This works for definitions of basic values as well as for object +references in which the $a$ is of type $\oid$. To increase +readability, we introduce the functions: +\begin{gather} +\begin{array}{llrlr} +\qquad\qquad&\definitionS\enspace&\operatorname{in\_pre\_state} &= \operatorname{fst} & \qquad \text{first component}\\ +\qquad\qquad&\definitionS\enspace&\operatorname{in\_post\_state} &= \operatorname{snd} & \qquad \text{second component} \\ +\qquad\qquad&\definitionS\enspace&\operatorname{reconst\_basetype} &= \operatorname{id} & \qquad \text{identity function} +\end{array} +\end{gather} + + +Let \_\inlineocl{.getBase} be an accessor of class $C$ yielding a +value of base-type $A_{base}$. Then its definition is of the form: +\begin{gather} + \begin{array}{lll} +\definitionS&\_\mocl{.getBase} &\ofType \ap C \Rightarrow A_{base}\\ +\where\enspace&X\mocl{.getBase} &= \operatorname{eval\_extract}\ap X\ap + (\operatorname{deref\_oid}_C\ap \operatorname{in\_post\_state}\ap\\ + & &\quad (\operatorname{select}_\text{getBase}\ap \operatorname{reconst\_basetype})) + \end{array} +\end{gather} + +Let \_\inlineocl{.getObject} be an accessor of class $C$ yielding a +value of object-type $A_{object}$. Then its definition is of the form: +\begin{gather} + \begin{array}{lll} +\definitionS&\_\mocl{.getObject} &\ofType \ap C \Rightarrow A_{object}\\ +\where\enspace&X\mocl{.getObject} &= \operatorname{eval\_extract}\ap X\ap + (\operatorname{deref\_oid}_C\ap \operatorname{in\_post\_state}\ap\\ + & &\quad (\operatorname{select}_\text{getObject}\ap + (\operatorname{deref\_oid}_C\ap\operatorname{in\_post\_state}))) + \end{array} +\end{gather} +The variant for an accessor yielding a collection is omitted here; its +construction follows by the application of the principles of the +former two. The respective variants +$\getAttrib{\_}{\text{$a$}\isasymOclATpre}$ were produced when +\inlineisar+in_post_state+ is replaced by +$\operatorname{in\_pre\_state}$. + +Examples for the construction of accessors via associations can be found in +\autoref{sec:eam-accessors}, the construction of accessors via attributes in +\autoref{sec:edm-accessors}. The construction of casts and type tests \verb+->oclIsTypeOf()+ and +\verb+->oclIsKindOf()+ is similarly. + +In the following, we discuss the role of multiplicities on the types of the +accessors. +Depending on the specified multiplicity, the evaluation of an attribute can +yield just a value (multiplicity \inlineocl{0..1} or \inlineocl{1}) +or a collection type like Set or Sequence of values (otherwise). +A multiplicity defines a lower bound as well as a possibly infinite upper +bound on the cardinality of the attribute's values. + + +\subsubsection{Single-Valued Attributes}\label{sec:single-valued-properties} +If the upper bound specified by the attribute's multiplicity is one, +then an evaluation of the attribute yields a single value. +Thus, the evaluation result is \emph{not} a collection. If the lower bound specified by the +multiplicity is zero, the evaluation is not required to yield a non-null value. In this case an +evaluation of the attribute can return $\isasymOclNull$ to indicate an +absence of value. + +To facilitate accessing attributes with multiplicity \inlineocl{0..1}, the OCL +standard states that single values can be used as sets by calling collection +operations on them. This implicit conversion of a value to a +\inlineocl{Set} is not defined by the standard. We argue that the resulting set +cannot be constructed the same way as when evaluating a \inlineocl{Set} +literal. Otherwise, $\isasymOclNull$ would be mapped to the singleton set +containing $\isasymOclNull$, but the standard demands that +the resulting set is empty in this case. The conversion should instead +be defined as follows: +\begin{ocl} +context OclAny::asSet():T + post: if self = null then result = Set{} + else result = Set{self} endif +\end{ocl} +% Changed self.isTypeOf(OCLVoid) to self = null to make it easier for the superficial reader + +\subsubsection{Collection-Valued Attributes}\label{sec:collection-valued-properties} +If the upper bound specified by the attribute's multiplicity is larger than one, +then an evaluation of the attribute yields a collection of values. This raises +the question whether $\isasymOclNull$ can belong to this collection. The OCL +standard states that $\isasymOclNull$ can be owned by collections. However, if +an attribute can evaluate to a collection containing $\isasymOclNull$, it is not +clear how multiplicity constraints should be interpreted for this attribute. The +question arises whether the $\isasymOclNull$ element should be counted or not +when determining the cardinality of the collection. Recall that $\isasymOclNull$ +denotes the absence of value in the case of a cardinality upper bound of one, so +we would assume that $\isasymOclNull$ is not counted. On the other hand, the +operation \inlineocl{size} defined for collections in OCL does count +$\isasymOclNull$. + +We propose to resolve this dilemma by regarding multiplicities as optional. This +point of view complies with the UML standard, that does not require lower and +upper bounds to be defined for multiplicities.\footnote{We are however aware + that a well-formedness rule of the UML standard does define a default bound + of one in case a lower or upper bound is not specified.} In case a +multiplicity is specified for an attribute, \ie, a lower and an upper bound +are provided, we require any collection the attribute evaluates to not +contain $\isasymOclNull$. This allows for a straightforward interpretation of +the multiplicity constraint. If bounds are not provided for an attribute, we +consider the attribute values to not be restricted in any way. Because in +particular the cardinality of the attribute's values is not bounded, the result +of an evaluation of the attribute is of collection type. As the range of values +that the attribute can assume is not restricted, the attribute can evaluate to a +collection containing $\isasymOclNull$. The attribute can also evaluate to +$\isasymOclInvalid$. Allowing multiplicities to be optional in this way gives +the modeler the freedom to define attributes that can assume the full ranges of +values provided by their types. However, we do not permit the omission of +multiplicities for association ends, since the values of association ends are +not only restricted by multiplicities, but also by other constraints enforcing +the semantics of associations. Hence, the values of association ends cannot be +completely unrestricted. + +\subsubsection{The Precise Meaning of Multiplicity Constraints} +We are now ready to define the meaning of multiplicity constraints by giving +equivalent invariants written in OCL\@. Let \inlineocl{a} be an attribute of a +class \inlineocl{C} with a multiplicity specifying a lower bound $m$ and an +upper bound $n$. Then we can define the multiplicity constraint on the values of +attribute \inlineocl{a} to be equivalent to the following invariants written in +OCL: +\begin{ocl} +context C inv lowerBound: a->size() >= m + inv upperBound: a->size() <= n + inv notNull: not a->includes(null) +\end{ocl} +If the upper bound $n$ is infinite, the second invariant is omitted. For the +definition of these invariants we are making use of the conversion of single +values to sets described in \autoref{sec:single-valued-properties}. If $n +\leq 1$, the attribute \inlineocl{a} evaluates to a single value, which is then +converted to a \inlineocl{Set} on which the \inlineocl{size} operation is +called. + +If a value of the attribute \inlineocl{a} includes a reference to a non-existent +object, the attribute call evaluates to $\isasymOclInvalid$. As a result, the +entire expressions evaluate to $\isasymOclInvalid$, and the invariants are not +satisfied. Thus, references to non-existent objects are ruled out by these +invariants. We believe that this result is appropriate, since we argue that the +presence of such references in a system state is usually not intended and likely +to be the result of an error. If the modeler wishes to allow references to +non-existent objects, she can make use of the possibility described above to +omit the multiplicity. + + +\subsection{Other Operations on States} +Defining $\_\isasymOclAllInstances$ +is straight-forward; the only difference is the property +$T\isasymOclAllInstances\isasymOclExcludes(\isasymOclNull)$ which is a +consequence of the fact that $\Null{}$'s are values and do not ``live'' in the +state. In our semantics which admits states with ``dangling references,'' it is +possible to define a counterpart to \inlineocl+_.oclIsNew()+ called +\inlineocl+_.oclIsDeleted()+ which asks if an object id (represented by an object +representation) is contained in the pre-state, but not the post-state. + +OCL does not guarantee that an operation only modifies the path-expressions +mentioned in the postcondition, \ie, it allows arbitrary relations from +pre-states to post-states. This framing problem is well-known (one of the +suggested solutions is~\cite{kosiuczenko:specification:2006}). We define +\begin{ocl} + (S:Set(OclAny))->oclIsModifiedOnly():Boolean +\end{ocl} +where \inlineocl|S| is a set of object representations, encoding +a set of $\oid$'s. The semantics of this operator is defined such that +for any object whose $\oid$ is \emph{not }represented in \inlineocl|S| +and that is defined in pre and post state, the corresponding object representation will not change +in the state transition. A simplified presentation is as follows: +\begin{gather*} +I\semantics{X\isasymMathOclIsModifiedOnly} (\sigma, \sigma') \equiv + \begin{cases} + \isasymbottom & \text{if $X' = \bottom \lor \text{null}\in X'$} \\ + \lift{\isasymforall i \isasymin M\spot + \sigma~i = \sigma'~i} & \text{otherwise}\mi{.} + \end{cases} +\end{gather*} +where $X' = I\semantics{X} (\sigma, \sigma')$ and $M= +(\dom~\sigma\cap\dom~\sigma') - \{ \HolOclOidOf x |~x \in\drop{X'}\}$. Thus, if +we require in a postcondition \inlineocl|Set{}->oclIsModifiedOnly()| and exclude via +\inlineocl+_.oclIsNew()+ and \inlineocl+_.oclIsDeleted()+ the existence of new +or deleted objects, the operation is a query in the sense of the OCL standard, \ie, +the \inlineocl|isQuery| property is true. So, whenever we have $ \tau +\isasymMathOclValid X\isasymOclExcluding(s.a)\isasymMathOclIsModifiedOnly$ and $ \tau +\isasymMathOclValid X\mocl{->forAll(}x\mocl{|not}(x \doteq s.a) \mocl{)}$, we can infer that $\tau +\isasymMathOclValid s.a \triangleq s.a\isasymOclATpre$. + + + + +\section{A Machine-checked Annex A} +\begin{figure*}[tb] + \mbox{}\hfill + \subfloat% + [The Isabelle jEdit environment. ]% + {\label{fig:jedit} \includegraphics[height=6.2cm]{jedit}}% + \hfill% + \hfill% + \subfloat[The generated formal document.]% + {\label{fig:pdf} \includegraphics[height=6.2cm]{pdf}} + \hfill\mbox{} + \caption{Generating documents with guaranteed syntactical and + semantical consistency.} + \label{fig:gener-docum-where} +\end{figure*} +Isabelle, as a framework for building formal +tools~\cite{wenzel.ea:building:2007}, provides the means for +generating \emph{formal documents}. With formal documents (such as +the one you are currently reading) we refer to documents that are +machine-generated and ensure certain formal guarantees. In particular, +all formal content (\eg, definitions, formulae, types) are checked for +consistency during the document generation. + +For writing documents, Isabelle supports the embedding of informal +texts using a \LaTeX-based markup language within the theory files. To +ensure the consistency, Isabelle supports to use, within these +informal texts, \emph{antiquotations} that refer to the formal parts +and that are checked while generating the actual document as +PDF\@. For example, in an informal text, the antiquotation +\inlineisar|@{$\text{thm}$ "not_not"}| will instruct Isabelle to +lock-up the (formally proven) theorem of name \inlineisar"ocl_not_not" +and to replace the antiquotation with the actual theorem, \ie, +\inlineocl{not (not x) $=$ x}. + +\autoref{fig:gener-docum-where} +illustrates this approach: \autoref{fig:jedit} shows the jEdit-based +development environment of Isabelle with an excerpt of one of the core +theories of Featherweight OCL\@. \autoref{fig:pdf} shows the generated +PDF document where all antiquotations are replaced. Moreover, +the document generation tools allows for defining syntactic sugar as +well as skipping technical details of the formalization. + + +Thus, applying the Featherweight OCL approach to writing an updated +Annex A that provides a formal semantics of the most fundamental +concepts of OCL would ensure +\begin{enumerate} +\item that all formal context is syntactically correct and well-typed, + and +\item all formal definitions and the derived logical rules are + semantically consistent. +\end{enumerate} +Overall, this would contribute to one of the main goals of the OCL 2.5 +RFP, as discussed at the OCL meeting in +Aachen~\cite{brucker.ea:summary-aachen:2013}. + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "root" +%%% End: + +% LocalWords: UML OCL implementors RFP OMG provers invariants +% LocalWords: wellfounded Denotational equalities diff --git a/document/lstisar.sty b/document/lstisar.sty new file mode 100644 index 0000000..e81e4e0 --- /dev/null +++ b/document/lstisar.sty @@ -0,0 +1,423 @@ + +\definecolor{OliveGreen} {cmyk}{0.64,0,0.95,0.40} +\definecolor{BrickRed} {cmyk}{0,0.89,0.94,0.28} +\definecolor{Blue} {cmyk}{1,1,0,0} +\definecolor{CornflowerBlue}{cmyk}{0.65,0.13,0,0} + +\newcommand{\subscr}[1]{\ensuremath{_{\mbox{#1}}}} +\newcommand{\supscr}[1]{\ensuremath{^{\mbox{#1}}}} +\lstdefinestyle{ISAR}{language=,% + basicstyle=\rmfamily,% + showspaces=false,% + showlines=false, + columns=flexible,% + morecomment=[s]{(*}{*)},% + morecomment=[s]{\{*}{*\}},% + morestring=*[b]",% + showstringspaces=false, + moredelim=*[is][\subscr]{\\<^bsub>}{\\<^esub>},% + moredelim=*[is][\supscr]{\\<^bsup>}{\\<^esup>},% + literate={% +%{\\}{\ensuremath{\mathfrak{Z}}}1%requires eufrak +%{\\}{\ensuremath{\mathfrak{z}}}1%requires eufrak +{\\}{\ensuremath{\zeta}}1% +%{\\}{\ensuremath{\mathrm{z}}}1% +%{\\}{\ensuremath{\mathcal{Z}}}1% +%{\\}{\ensuremath{\mathfrak{Y}}}1%requires eufrak +%{\\}{\ensuremath{\mathfrak{y}}}1%requires eufrak +%{\\}{\ensuremath{\mathrm{y}}}1% +%{\\}{\ensuremath{\mathcal{Y}}}1% +%{\\}{\mbox{\yen}}1%requires amssymb,% +%{\\}{\ensuremath{\mathfrak{X}}}1%requires eufrak +%{\\}{\ensuremath{\mathfrak{x}}}1%requires eufrak +{\\}{\ensuremath{\Xi}}1% +{\\}{\ensuremath{\xi}}1% +%{\\}{\ensuremath{\mathrm{x}}}1% +%{\\}{\ensuremath{\mathcal{X}}}1% +%{\\}{\ensuremath{\mathfrak{W}}}1%requires eufrak +%{\\}{\ensuremath{\mathfrak{w}}}1%requires eufrak +{\\}{\ensuremath{\wr}}1% +{\\}{\ensuremath{\wp}}1% +%{\\}{\ensuremath{\mathrm{w}}}1% +%{\\}{\ensuremath{\mathcal{W}}}1% +%{\\}{\ensuremath{\mathfrak{V}}}1%requires eufrak +%{\\}{\ensuremath{\mathfrak{v}}}1%requires eufrak +%{\\}{\ensuremath{\mathrm{v}}}1% +%{\\}{\ensuremath{\mathcal{V}}}1% +%{\\}{\ensuremath{\mathfrak{U}}}1%requires eufrak +%{\\}{\ensuremath{\mathfrak{u}}}1%requires eufrak +{\\}{\ensuremath{\Upsilon}}1% +{\\}{\ensuremath{\upsilon}}1% +{\\}{\ensuremath{\uplus}}1% +{\\}{\ensuremath{\biguplus\,}}1% +{\\}{\ensuremath{\Uparrow}}1% +{\\}{\ensuremath{\uparrow}}1% +{\\}{\ensuremath{\Updownarrow}}1% +{\\}{\ensuremath{\updownarrow}}1% +{\\}{\ensuremath{\unrhd}}1% +{\\<^sub>}{\textsubscript}0% +{\\}{\ensuremath{\unlhd}}1% +{\\}{\ensuremath{\cup}}1% +{\\}{\ensuremath{\bigcup\,}}1% +%{\\}{\ensuremath{\mathrm{u}}}1% +%{\\}{\ensuremath{\mathcal{U}}}1% +{\\}{\ensuremath{\mathtwosuperior}}1%requires latin1,% +{\\}{\ensuremath{\vdash}}1% +{\\}{\ensuremath{\models}}1% +{\\}{\ensuremath{\models}}1% +{\\}{\ensuremath{\vdash\!\!\!\vdash}}1% +{\\}{\ensuremath{\mid\!\models}}1% +%{\\}{\ensuremath{\mathfrak{T}}}1%requires eufrak +%{\\}{\ensuremath{\mathfrak{t}}}1%requires eufrak +{\\}{\ensuremath{\triangleright}}1% +{\\}{\ensuremath{\triangleq}}1%requires amssymb,% +{\\}{\ensuremath{\triangleleft}}1% +{\\}{\ensuremath{\triangle}}1% +{\\}{\ensuremath{\top}}1% +{\\}{\ensuremath{\times}}1% +{\\}{\ensuremath{\maththreesuperior}}1%requires latin1,% +{\\}{\mbox{\rm\textthreequarters}}1%requires latin1,% +{\\}{\ensuremath{\vartheta}}1% +{\\}{\ensuremath{\Theta}}1% +%{\\}{\ensuremath{\mathrm{t}}}1% +%{\\}{\ensuremath{\mathcal{T}}}1% +{\\}{\ensuremath{\tau}}1% +{\\}{\ensuremath{\surd}}1% +{\\}{\ensuremath{\supseteq}}1% +{\\}{\ensuremath{\supset}}1% +{\\}{\ensuremath{\sum\,}}1% +{\\}{\ensuremath{\succeq}}1% +{\\}{\ensuremath{\succ}}1% +{\\}{\ensuremath{\subseteq}}1% +{\\}{\ensuremath{\subset}}1% +{\\}{\ensuremath{\diamond}}1% +{\\}{\ensuremath{\dashv}}1% +{\\}{\ensuremath{\star}}1% +%{\\}{\ensuremath{\mathfrak{S}}}1%requires eufrak +%{\\}{\ensuremath{\mathfrak{s}}}1%requires eufrak +%{\\}{\ensuremath{\sqcup}}1% +%{\\}{\ensuremath{\bigsqcup\,}}1% +%{\\}{\ensuremath{\sqsupseteq}}1% +%{\\}{\ensuremath{\sqsupset}}1%requires amssym,% +%{\\}{\ensuremath{\sqsubseteq}}1% +{\\}{\ensuremath{\sqsubset}}1% +%{\\}{\ensuremath{\sqcap}}1% +%{\\}{\ensuremath{\bigsqcap\,}}1%requires masmath,% +%{\\}{\ensuremath{\spadesuit}}1% +%{\\}{\ensuremath{~~}}1% +%{\\}{\ensuremath{\smile}}1% +{\\}{\ensuremath{\simeq}}1% +{\\}{\ensuremath{\sim}}1% +{\\}{\ensuremath{\Sigma}}1% +{\\}{\ensuremath{\sigma}}1% +{\\}{\ensuremath{\sharp}}1% +%{\\}{\ensuremath{\mathrm{s}}}1% +%{\\}{\ensuremath{\mathcal{S}}}1% +{\\
}{\mbox{\rm\S}}1% +%{\\}{\ensuremath{\mathfrak{R}}}1%requires eufrak +%{\\}{\ensuremath{\mathfrak{r}}}1%requires eufrak +{\\}{\ensuremath{\mathclose{\mid\mkern-3mu)}}}1% +{\\}{\ensuremath{\rightleftharpoons}}2% +{\\}{\ensuremath{\rightharpoonup}}2% +%{\\}{\ensuremath{\rightharpoondown}}1% +{\\}{\ensuremath{\Rightarrow}}2% +{\\}{\ensuremath{\rightarrow}}2% +{\\}{\ensuremath{\restriction}}2% +{\\}{\ensuremath{\varrho}}1% +%{\\}{\ensuremath{\rhd}}1% +{\\}{\ensuremath{\rfloor}}1% +%{\\}{\ensuremath{\mathrm{r}}}1% +%{\\}{\ensuremath{\mathcal{R}}}1% +%{\\}{\mbox{\rm\textregistered}}1% +%{\\}{\ensuremath{\Re}}1% +%{\\}{\ensuremath{\mathrm{I}\mkern-3.8mu\mathrm{R}}}1% +{\\}{\ensuremath{\rceil}}1% +{\\}{\ensuremath{\mathclose{\rbrack\mkern-3mu\rbrack}}}1% +{\\}{\ensuremath{\mathclose{\mid\mkern-4.5mu\rbrace}}}1% +%{\\}{\ensuremath{\mathrm{Q}\mkern-16mu{\phantom{\mathrm{t}}\vrule}\mkern10mu}}1% +{\\}{\ensuremath{\rangle}}1% +%{\\}{\mbox{\rm\textquestiondown}}1% +%{\\}{\ensuremath{\mathfrak{Q}}}1%requires eufrak +%{\\}{\ensuremath{\mathfrak{q}}}1%requires eufrak +%{\\}{\ensuremath{\mathrm{q}}}1% +%{\\}{\ensuremath{\mathcal{Q}}}1% +{\\}{\ensuremath{\Psi}}1% +{\\}{\ensuremath{\psi}}1% +{\\}{\ensuremath{\propto}}1% +{\\}{\ensuremath{\prod\,}}1% +{\\}{\ensuremath{\preceq}}1% +{\\}{\ensuremath{\prec}}1% +%{\\}{\ensuremath{\mathfrak{P}}}1%requires eufrak +%{\\}{\ensuremath{\mathfrak{p}}}1%requires eufrak +%{\\}{\ensuremath{\pounds}}1% +{\\}{\ensuremath{\pm}}1% +{\\}{\ensuremath{\Pi}}1% +{\\}{\ensuremath{\pi}}1% +{\\}{\ensuremath{\varphi}}1% +{\\}{\ensuremath{\Phi}}1% +%{\\

}{\ensuremath{\mathrm{p}}}1% +%{\\

}{\ensuremath{\mathcal{P}}}1% +{\\}{\ensuremath{\partial}}1% +{\\}{\ensuremath{\parallel}}1% +{\\}{\mbox{\rm\P}}1% +{\\}{\ensuremath{\otimes}}1% +{\\}{\ensuremath{\bigotimes\,}}1% +%{\\}{\ensuremath{\oslash}}1% +{\\}{\ensuremath{\vee}}1% +{\\}{\ensuremath{\bigvee}}1% +%{\\}{\mbox{\rm\textordmasculine}}1% +%{\\}{\mbox{\rm\textordfeminine}}1% +{\\}{\ensuremath{\oplus}}1% +{\\}{\ensuremath{\bigoplus\,}}1% +%{\\}{\ensuremath{\mathfrak{O}}}1%requires eufrak +%{\\}{\ensuremath{\mathfrak{o}}}1%requires eufrak +%{\\}{\ensuremath{\mathonesuperior}}1%requires latin1,% +%{\\}{\mbox{\rm\textonequarter}}1%requires latin1,% +%{\\}{\mbox{\rm\textonehalf}}1%requires latin1,% +{\\}{\ensuremath{\ominus}}1% +%{\\}{\ensuremath{\Omega}}1% +%{\\}{\ensuremath{\omega}}1% +%{\\}{\ensuremath{\oint\,}}1% +%{\\}{\ensuremath{\mathrm{o}}}1% +%{\\}{\ensuremath{\mathcal{O}}}1% +{\\}{\ensuremath{\odot}}1% +{\\}{\ensuremath{\bigodot\,}}1% +{\\}{\ensuremath{\nu}}1% +{\\}{\ensuremath{\notin}}1% +{\\}{\ensuremath{\neq}}1% +{\\}{\ensuremath{\neg}}1% +%{\\}{\ensuremath{\mathfrak{N}}}1%requires eufrak +%{\\}{\ensuremath{\mathfrak{n}}}1%requires eufrak +%{\\}{\ensuremath{\mathrm{n}}}1% +%{\\}{\ensuremath{\mathcal{N}}}1% +%{\\}{\ensuremath{\natural}}1% +{\\}{\ensuremath{\mathrm{I}\mkern-3.8mu\mathrm{N}}}1% +{\\}{\ensuremath{\nabla}}1% +{\\}{\ensuremath{\mu}}1% +%{\\}{\ensuremath{\mathfrak{M}}}1%requires eufrak +%{\\}{\ensuremath{\mathfrak{m}}}1%requires eufrak +{\\}{\ensuremath{\mp}}1% +{\\}{\ensuremath{\Relbar}}1% +{\\}{\ensuremath{\relbar}}1% +{\\}{\ensuremath{\mho}}1%requires amssym,% +%{\\}{\ensuremath{\mathrm{m}}}1% +%{\\}{\ensuremath{\mathcal{M}}}1% +{\\}{\ensuremath{\mapsto}}1% +{\\}{\ensuremath{\mathopen{(\mkern-3mu\mid}}}1% +%{\\}{\ensuremath{\lozenge}}1%requires amssym,% +{\\}{\ensuremath{\Longrightarrow}}3% +{\\}{\ensuremath{\longrightarrow}}3% +{\\}{\ensuremath{\longrightarrow}}4% +{\\}{\ensuremath{\longmapsto}}3% +{\\}{\ensuremath{\Longleftrightarrow}}3% +{\\}{\ensuremath{\longleftrightarrow}}3% +{\\}{\ensuremath{\Longleftarrow}}3% +{\\}{\ensuremath{\longleftarrow}}3% +{\\}{\ensuremath{\ll}}1% +%{\\}{\ensuremath{\mathfrak{L}}}1%requires eufrak +%{\\}{\ensuremath{\mathfrak{l}}}1%requires eufrak +%{\\}{\ensuremath{\lhd}}1% +{\\}{\ensuremath{\lfloor}}1% +{\\}{\ensuremath{\lesssim}}1%requires amssymb,% +%{\\}{\ensuremath{\lessapprox}}1%requires amssymb,% +%{\\}{\ensuremath{\mathrm{l}}}1% +%{\\}{\ensuremath{\mathcal{L}}}1% +{\\}{\ensuremath{\Leftrightarrow}}1% +{\\}{\ensuremath{\leftrightarrow}}1% +%{\\}{\ensuremath{\leftharpoonup}}1% +%{\\}{\ensuremath{\leftharpoondown}}1% +{\\}{\ensuremath{\Leftarrow}}1% +{\\}{\ensuremath{\leftarrow}}1% +{\\}{\ensuremath{\le}}1% +{\\}{\ensuremath{\leadsto}}2%requires amssym,% +{\\}{\ensuremath{\lceil}}1% +{\\}{\ensuremath{\mathopen{\lbrack\mkern-3mu\lbrack}}}1% +{\\}{\ensuremath{\mathopen{\lbrace\mkern-4.5mu\mid}}}1% +{\\}{\ensuremath{\langle}}1% +{\\}{\ensuremath{\Lambda}}1% +{\\}{\ensuremath{\lambda}}1% +%{\\}{\ensuremath{\mathfrak{K}}}1%requires eufrak +%{\\}{\ensuremath{\mathfrak{k}}}1%requires eufrak +%{\\}{\ensuremath{\mathrm{k}}}1% +%{\\}{\ensuremath{\mathcal{K}}}1% +{\\}{\ensuremath{\kappa}}1% +{\\}{\ensuremath{\Join}}1%requires amssym,% +%{\\}{\ensuremath{\mathfrak{J}}}1%requires eufrak +%{\\}{\ensuremath{\mathfrak{j}}}1%requires eufrak +%{\\}{\ensuremath{\mathrm{j}}}1% +%{\\}{\ensuremath{\mathcal{J}}}1% +{ISABELLE}{\$ISABELLE}8% +{\\}{\ensuremath{\iota}}1% +{\\}{\ensuremath{{}^{-1}}}1% +{\\}{\ensuremath{\cap}}1% +{\\}{\ensuremath{\bigcap\,}}1% +{\\}{\ensuremath{\mathsf{Z}\mkern-7.5mu\mathsf{Z}}}1% +{\\}{\ensuremath{\int\,}}1% +{\\}{\ensuremath{\infty}}1% +{\\}{\ensuremath{\in}}1% +{\\}{\mbox{\i}}1% +%{\\}{\ensuremath{\Im}}1% +%{\\}{\ensuremath{\mathfrak{I}}}1%requires eufrak +%{\\}{\ensuremath{\mathfrak{i}}}1%requires eufrak +%{\\}{\ensuremath{\mathrm{i}}}1% +%{\\}{\ensuremath{\mathcal{I}}}1% +%{\\}{\mbox{\rm-}}1% +%{\\}{\mbox{\H\relax}}1% +{\\}{\ensuremath{\hookrightarrow}}1% +{\\}{\ensuremath{\hookleftarrow}}1% +%{\\}{\ensuremath{\mathfrak{H}}}1%requires eufrak +%{\\}{\ensuremath{\mathfrak{h}}}1%requires eufrak +%{\\}{\ensuremath{\mathrm{h}}}1% +%{\\}{\ensuremath{\mathcal{H}}}1% +%{\\}{\ensuremath{\heartsuit}}1% +%{\\}{\mbox{\frqq}}1%requires babel ,% +%{\\}{\mbox{\flqq}}1%requires babel ,% +{\\}{\ensuremath{\gtrsim}}1%requires amssymb,% +{\\}{\ensuremath{\gtrapprox}}1%requires amssymb,% +{\\}{\ensuremath{\gg}}1% +%{\\}{\ensuremath{\mathfrak{G}}}1%requires eufrak +%{\\}{\ensuremath{\mathfrak{g}}}1%requires eufrak +%{\\}{\ensuremath{\mathrm{g}}}1% +%{\\}{\ensuremath{\mathcal{G}}}1% +{\\}{\ensuremath{\ge}}1% +{\\}{\ensuremath{\Gamma}}1% +{\\}{\ensuremath{\gamma}}1% +{\\}{\ensuremath{\frown}}1% +{\\}{\ensuremath{\forall\,}}1% +{\\}{\ensuremath{\bigwedge\,}}1% +{\\}{\ensuremath{\flat}}1% +%{\\}{\ensuremath{\mathfrak{F}}}1%requires eufrak +%{\\}{\ensuremath{\mathfrak{f}}}1%requires eufrak +%{\\}{\ensuremath{\mathrm{f}}}1% +%{\\}{\ensuremath{\mathcal{F}}}1% +{\\}{\ensuremath{\exists\,}}1% +%{\\}{\mbox{\rm\textexclamdown}}1% +%{\\}{\mbox{\textgreek{\euro}}}1%requires greek babel,% +%{\\}{\ensuremath{\eta}}1% +{\\}{\ensuremath{\equiv}}1% +{\\}{\ensuremath{\varepsilon}}1% +{\\}{\ensuremath{\emptyset}}1% +%{\\}{\ensuremath{\mathrm{e}}}1% +%{\\}{\ensuremath{\mathcal{E}}}1% +%{\\}{\ensuremath{\mathfrak{E}}}1%requires eufrak +%{\\}{\ensuremath{\mathfrak{e}}}1%requires eufrak +{\\}{\ensuremath{\Downarrow}}1% +{\\}{\ensuremath{\downarrow}}1% +{\\}{\ensuremath{\dots}}1% +{\\}{\ensuremath{\doteq}}1% +{\\

}{\ensuremath{\div}}1% +{\\}{\mbox{\"\relax}}1% +%{\\}{\ensuremath{\diamondsuit}}1% +{\\}{\ensuremath{\Diamond}}1%requires amssym,% +%{\\}{\ensuremath{\mathrm{d}}}1% +%{\\}{\ensuremath{\mathcal{D}}}1% +%{\\}{\ensuremath{\Delta}}1% +{\\}{\ensuremath{\delta}}1% +{\\}{\mbox{\rm\textdegree}}1%requires latin1,% +%{\\
}{\ensuremath{\mathfrak{D}}}1%requires eufrak +%{\\
}{\ensuremath{\mathfrak{d}}}1%requires eufrak +{\\}{\ensuremath{\ddagger}}1% +{\\}{\ensuremath{\dagger}}1% +%{\\}{\mbox{\textcurrency}}1%requires textcomp,% +%{\\}{\mbox{\rm\copyright}}1% +{\\}{\ensuremath{\coprod\,}}1% +{\\}{\ensuremath{\cong}}1% +%{\\}{\ensuremath{\mathrm{C}\mkern-15mu{\phantom{\mathrm{t}}\vrule}\mkern9mu}}1% +{\\}{\ensuremath{\mathrel{::}}}1% +{\\}{\ensuremath{\clubsuit}}1% +{\\}{\ensuremath{\circ}}1% +{\\}{\ensuremath{\chi}}1% +%{\\}{\mbox{\textcent}}1%requires textcomp,% +%{\\}{\ensuremath{\mathrm{c}}}1% +%{\\}{\ensuremath{\mathcal{C}}}1% +{\\}{\mbox{\c\relax}}1% +{\\}{\ensuremath{\cdots}}1% +{\\}{\ensuremath{\vdots}}1% +{\\}{\ensuremath{\cdot}}1% +%{\\}{\ensuremath{\mathfrak{C}}}1%requires eufrak +%{\\}{\ensuremath{\mathfrak{c}}}1%requires eufrak +{\\}{\scriptscriptstyle{\bullet}}}}1% +{\\}{\ensuremath{\Box}}1%requires amssym,% +%{\\}{\ensuremath{\bowtie}}1% +{\\}{\ensuremath{\bot}}1% +%{\\}{\ensuremath{\mathrm{I}\mkern-3.8mu\mathrm{B}}}1% +{\\}{\ensuremath{\beta}}1% +%{\\}{\ensuremath{\mathrm{b}}}1% +%{\\}{\ensuremath{\mathcal{B}}}1% +%{\\}{\ensuremath{\mathfrak{B}}}1%requires eufrak +%{\\}{\ensuremath{\mathfrak{b}}}1%requires eufrak +{\\}{\ensuremath{\mid}}1% +%{\\}{\ensuremath{\asymp}}1% +{\\}{\ensuremath{\approx}}1% +{\\}{\ensuremath{\angle}}1% +{\\}{\ensuremath{\wedge}}1% +{\\}{\ensuremath{\bigwedge}}1% +%{\\}{\ensuremath{\amalg}}1% +{\\}{\ensuremath{\alpha}}1% +{\\}{\ensuremath{\aleph}}1% +%{\\}{\ensuremath{\mathrm{a}}}1% +%{\\}{\ensuremath{\mathcal{A}}}1% +%{\\}{\mbox{\'\relax}}1% +{\\}{\ensuremath{\mathfrak{A}}}1%requires eufrak +%{\\}{\ensuremath{\mathfrak{a}}}1%requires eufrak +{`}{$`$}1% +{``}{$``$}1% + % non-standard: + % {\\}{$\underset{c}{\longrightarrow}$}1% + {\\}{\raisebox{-.8ex}{$\overrightarrow{\enspace{\mbox{\scriptsize $c$}}\enspace}$}}3% + {}{$n$}1% + {IF}{$\mathtt{IF}$}4% + {THEN}{$\mathtt{THEN}$}5% + {PUT}{$\mathtt{PUT}$}3% + {ELSE}{$\mathtt{ELSE}$}5% + {DO}{$\mathtt{DO}$}3% + {WHILE}{$\mathtt{WHILE}$}7% + {AWHILE}{$\mathtt{AWHILE}$}8% + {ASSERT}{$\mathtt{ASSERT}$}8% + {STOP}{$\mathtt{STOP}$}5% + {SKIP}{$\mathtt{SKIP}$}5% + {\\}{$_n$}1% + {}{$\mathit{rule}$}3% + {}{$\mathit{rule}$}4% + {}{$\mathit{rules}$}5% + {}{$\mathit{term}$}4% + {}{$\mathit{term}_1$}4% + {}{$\mathit{term}_n$}4% + {}{$\mathit{function}$}9% + {}{$\mathit{name}$}4% + {}{$\mathit{name}_n$}4% + {}{$\mathit{name}_1$}4% + {}{$a_1$}1% + {}{$x_1$}1% + {}{$a_n$}1% + {}{$x_n$}1% + {}{$C$}1% + },% + classoffset=0,% + keywordstyle=\textbf,% + morekeywords={theory,end,imports,begin},% + classoffset=1,% + keywordstyle=\textbf,% + morekeywords={text,txt,finally,next,also,with,moreover,ultimately,thus,prefer,defer,declare,apply,of,OF,THEN,intros,in,fix,assume,from,this,show,have,and,note,let,hence,where,using},% then, and + classoffset=2,% + keywordstyle=\color{Blue}\textbf,% + morekeywords={axclass,class,instance,recdef,primrec,constdefs,consts_code,types_code,consts,axioms,syntax,typedecl,arities,types,translations,inductive,typedef,datatype,record,instance,defs,specification,proof,test_spec,lemmas,lemma,assumes,shows,definition,fun,function,theorem,case},% + classoffset=3,% + keywordstyle=\color{BrickRed}\textbf,% + morekeywords={oops,sorry},% + classoffset=4,% + keywordstyle=\color{OliveGreen}\textbf,% + morekeywords={store_test_thm,qed,done,by},% + classoffset=5,% + keywordstyle=\textsl,% + morekeywords={frule,subst,erule,drule,rule,rule_tac,case_tac,insert,rotate_tac,unfold,fold,assumption,drule_tac},% + classoffset=6,% + keywordstyle=\color{Blue}\textbf,% + morekeywords={binder,infixl},% + classoffset=6,% + keywordstyle=\color{CornflowerBlue}\textbf,% + morekeywords={thm,export_test_data,generate_test_script,generate_code,gen_test_script,gen_test_data,quickcheck,testgen_params,quickcheck_params},% +} +\lstnewenvironment{isar}[1][]{\lstset{style=ISAR,#1}}{} +\lstnewenvironment{smallisar}[1][]{\lstset{style=ISAR,basicstyle=\small\sffamily,#1}}{} +\def\inlineisar{\lstinline[style=ISAR,breaklines=true,mathescape,breakatwhitespace=true]} diff --git a/document/prooftree.sty b/document/prooftree.sty new file mode 100644 index 0000000..abb7d44 --- /dev/null +++ b/document/prooftree.sty @@ -0,0 +1,347 @@ +\message{} +%% Build proof tree for Natural Deduction, Sequent Calculus, etc. +%% WITH SHORTENING OF PROOF RULES! +%% Paul Taylor, begun 10 Oct 1989 +%% *** THIS IS ONLY A PRELIMINARY VERSION AND THINGS MAY CHANGE! *** +%% +%% 2 Aug 1996: fixed \mscount and \proofdotnumber +%% +%% \prooftree +%% hyp1 produces: +%% hyp2 +%% hyp3 hyp1 hyp2 hyp3 +%% \justifies -------------------- rulename +%% concl concl +%% \thickness=0.08em +%% \shiftright 2em +%% \using +%% rulename +%% \endprooftree +%% +%% where the hypotheses may be similar structures or just formulae. +%% +%% To get a vertical string of dots instead of the proof rule, do +%% +%% \prooftree which produces: +%% [hyp] +%% \using [hyp] +%% name . +%% \proofdotseparation=1.2ex .name +%% \proofdotnumber=4 . +%% \leadsto . +%% concl concl +%% \endprooftree +%% +%% Within a prooftree, \[ and \] may be used instead of \prooftree and +%% \endprooftree; this is not permitted at the outer level because it +%% conflicts with LaTeX. Also, +%% \Justifies +%% produces a double line. In LaTeX you can use \begin{prooftree} and +%% \end{prootree} at the outer level (however this will not work for the inner +%% levels, but in any case why would you want to be so verbose?). +%% +%% All of of the keywords except \prooftree and \endprooftree are optional +%% and may appear in any order. They may also be combined in \newcommand's +%% eg "\def\Cut{\using\sf cut\thickness.08em\justifies}" with the abbreviation +%% "\prooftree hyp1 hyp2 \Cut \concl \endprooftree". This is recommended and +%% some standard abbreviations will be found at the end of this file. +%% +%% \thickness specifies the breadth of the rule in any units, although +%% font-relative units such as "ex" or "em" are preferable. +%% It may optionally be followed by "=". +%% \proofrulebreadth=.08em or \setlength\proofrulebreadth{.08em} may also be +%% used either in place of \thickness or globally; the default is 0.04em. +%% \proofdotseparation and \proofdotnumber control the size of the +%% string of dots +%% +%% If proof trees and formulae are mixed, some explicit spacing is needed, +%% but don't put anything to the left of the left-most (or the right of +%% the right-most) hypothesis, or put it in braces, because this will cause +%% the indentation to be lost. +%% +%% By default the conclusion is centered wrt the left-most and right-most +%% immediate hypotheses (not their proofs); \shiftright or \shiftleft moves +%% it relative to this position. (Not sure about this specification or how +%% it should affect spreading of proof tree.) +% +% global assignments to dimensions seem to have the effect of stretching +% diagrams horizontally. +% +%%========================================================================== + +\def\introrule{{\cal I}}\def\elimrule{{\cal E}}%% +\def\andintro{\using{\land}\introrule\justifies}%% +\def\impelim{\using{\Rightarrow}\elimrule\justifies}%% +\def\allintro{\using{\forall}\introrule\justifies}%% +\def\allelim{\using{\forall}\elimrule\justifies}%% +\def\falseelim{\using{\bot}\elimrule\justifies}%% +\def\existsintro{\using{\exists}\introrule\justifies}%% + +%% #1 is meant to be 1 or 2 for the first or second formula +\def\andelim#1{\using{\land}#1\elimrule\justifies}%% +\def\orintro#1{\using{\lor}#1\introrule\justifies}%% + +%% #1 is meant to be a label corresponding to the discharged hypothesis/es +\def\impintro#1{\using{\Rightarrow}\introrule_{#1}\justifies}%% +\def\orelim#1{\using{\lor}\elimrule_{#1}\justifies}%% +\def\existselim#1{\using{\exists}\elimrule_{#1}\justifies} + +%%========================================================================== + +\newdimen\proofrulebreadth \proofrulebreadth=.05em +\newdimen\proofdotseparation \proofdotseparation=1.25ex +\newdimen\proofrulebaseline \proofrulebaseline=2ex +\newcount\proofdotnumber \proofdotnumber=3 +\let\then\relax +\def\hfi{\hskip0pt plus.0001fil} +\mathchardef\squigto="3A3B +% +% flag where we are +\newif\ifinsideprooftree\insideprooftreefalse +\newif\ifonleftofproofrule\onleftofproofrulefalse +\newif\ifproofdots\proofdotsfalse +\newif\ifdoubleproof\doubleprooffalse +\let\wereinproofbit\relax +% +% dimensions and boxes of bits +\newdimen\shortenproofleft +\newdimen\shortenproofright +\newdimen\proofbelowshift +\newbox\proofabove +\newbox\proofbelow +\newbox\proofrulename +% +% miscellaneous commands for setting values +\def\shiftproofbelow{\let\next\relax\afterassignment\setshiftproofbelow\dimen0 } +\def\shiftproofbelowneg{\def\next{\multiply\dimen0 by-1 }% +\afterassignment\setshiftproofbelow\dimen0 } +\def\setshiftproofbelow{\next\proofbelowshift=\dimen0 } +\def\setproofrulebreadth{\proofrulebreadth} + +%============================================================================= +\def\prooftree{% NESTED ZERO (\ifonleftofproofrule) +% +% first find out whether we're at the left-hand end of a proof rule +\ifnum \lastpenalty=1 +\then \unpenalty +\else \onleftofproofrulefalse +\fi +% +% some space on left (except if we're on left, and no infinity for outermost) +\ifonleftofproofrule +\else \ifinsideprooftree + \then \hskip.5em plus1fil + \fi +\fi +% +% begin our proof tree environment +\bgroup% NESTED ONE (\proofbelow, \proofrulename, \proofabove, +% \shortenproofleft, \shortenproofright, \proofrulebreadth) +\setbox\proofbelow=\hbox{}\setbox\proofrulename=\hbox{}% +\let\justifies\proofover\let\leadsto\proofoverdots\let\Justifies\proofoverdbl +\let\using\proofusing\let\[\prooftree +\ifinsideprooftree\let\]\endprooftree\fi +\proofdotsfalse\doubleprooffalse +\let\thickness\setproofrulebreadth +\let\shiftright\shiftproofbelow \let\shift\shiftproofbelow +\let\shiftleft\shiftproofbelowneg +\let\ifwasinsideprooftree\ifinsideprooftree +\insideprooftreetrue +% +% now begin to set the top of the rule (definitions local to it) +\setbox\proofabove=\hbox\bgroup$\displaystyle % NESTED TWO +\let\wereinproofbit\prooftree +% +% these local variables will be copied out: +\shortenproofleft=0pt \shortenproofright=0pt \proofbelowshift=0pt +% +% flags to enable inner proof tree to detect if on left: +\onleftofproofruletrue\penalty1 +} + +%============================================================================= +% end whatever box and copy crucial values out of it +\def\eproofbit{% NESTED TWO +% +% various hacks applicable to hypothesis list +\ifx \wereinproofbit\prooftree +\then \ifcase \lastpenalty + \then \shortenproofright=0pt % 0: some other object, no indentation + \or \unpenalty\hfil % 1: empty hypotheses, just glue + \or \unpenalty\unskip % 2: just had a tree, remove glue + \else \shortenproofright=0pt % eh? + \fi +\fi +% +% pass out crucial values from scope +\global\dimen0=\shortenproofleft +\global\dimen1=\shortenproofright +\global\dimen2=\proofrulebreadth +\global\dimen3=\proofbelowshift +\global\dimen4=\proofdotseparation +\global\count255=\proofdotnumber +% +% end the box +$\egroup % NESTED ONE +% +% restore the values +\shortenproofleft=\dimen0 +\shortenproofright=\dimen1 +\proofrulebreadth=\dimen2 +\proofbelowshift=\dimen3 +\proofdotseparation=\dimen4 +\proofdotnumber=\count255 +} + +%============================================================================= +\def\proofover{% NESTED TWO +\eproofbit % NESTED ONE +\setbox\proofbelow=\hbox\bgroup % NESTED TWO +\let\wereinproofbit\proofover +$\displaystyle +}% +% +%============================================================================= +\def\proofoverdbl{% NESTED TWO +\eproofbit % NESTED ONE +\doubleprooftrue +\setbox\proofbelow=\hbox\bgroup % NESTED TWO +\let\wereinproofbit\proofoverdbl +$\displaystyle +}% +% +%============================================================================= +\def\proofoverdots{% NESTED TWO +\eproofbit % NESTED ONE +\proofdotstrue +\setbox\proofbelow=\hbox\bgroup % NESTED TWO +\let\wereinproofbit\proofoverdots +$\displaystyle +}% +% +%============================================================================= +\def\proofusing{% NESTED TWO +\eproofbit % NESTED ONE +\setbox\proofrulename=\hbox\bgroup % NESTED TWO +\let\wereinproofbit\proofusing +\kern0.3em$ +} + +%============================================================================= +\def\endprooftree{% NESTED TWO +\eproofbit % NESTED ONE +% \dimen0 = length of proof rule +% \dimen1 = indentation of conclusion wrt rule +% \dimen2 = new \shortenproofleft, ie indentation of conclusion +% \dimen3 = new \shortenproofright, ie +% space on right of conclusion to end of tree +% \dimen4 = space on right of conclusion below rule + \dimen5 =0pt% spread of hypotheses +% \dimen6, \dimen7 = height & depth of rule +% +% length of rule needed by proof above +\dimen0=\wd\proofabove \advance\dimen0-\shortenproofleft +\advance\dimen0-\shortenproofright +% +% amount of spare space below +\dimen1=.5\dimen0 \advance\dimen1-.5\wd\proofbelow +\dimen4=\dimen1 +\advance\dimen1\proofbelowshift \advance\dimen4-\proofbelowshift +% +% conclusion sticks out to left of immediate hypotheses +\ifdim \dimen1<0pt +\then \advance\shortenproofleft\dimen1 + \advance\dimen0-\dimen1 + \dimen1=0pt +% now it sticks out to left of tree! + \ifdim \shortenproofleft<0pt + \then \setbox\proofabove=\hbox{% + \kern-\shortenproofleft\unhbox\proofabove}% + \shortenproofleft=0pt + \fi +\fi +% +% and to the right +\ifdim \dimen4<0pt +\then \advance\shortenproofright\dimen4 + \advance\dimen0-\dimen4 + \dimen4=0pt +\fi +% +% make sure enough space for label +\ifdim \shortenproofright<\wd\proofrulename +\then \shortenproofright=\wd\proofrulename +\fi +% +% calculate new indentations +\dimen2=\shortenproofleft \advance\dimen2 by\dimen1 +\dimen3=\shortenproofright\advance\dimen3 by\dimen4 +% +% make the rule or dots, with name attached +\ifproofdots +\then + \dimen6=\shortenproofleft \advance\dimen6 .5\dimen0 + \setbox1=\vbox to\proofdotseparation{\vss\hbox{$\cdot$}\vss}% + \setbox0=\hbox{% + \advance\dimen6-.5\wd1 + \kern\dimen6 + $\vcenter to\proofdotnumber\proofdotseparation + {\leaders\box1\vfill}$% + \unhbox\proofrulename}% +\else \dimen6=\fontdimen22\the\textfont2 % height of maths axis + \dimen7=\dimen6 + \advance\dimen6by.5\proofrulebreadth + \advance\dimen7by-.5\proofrulebreadth + \setbox0=\hbox{% + \kern\shortenproofleft + \ifdoubleproof + \then \hbox to\dimen0{% + $\mathsurround0pt\mathord=\mkern-6mu% + \cleaders\hbox{$\mkern-2mu=\mkern-2mu$}\hfill + \mkern-6mu\mathord=$}% + \else \vrule height\dimen6 depth-\dimen7 width\dimen0 + \fi + \unhbox\proofrulename}% + \ht0=\dimen6 \dp0=-\dimen7 +\fi +% +% set up to centre outermost tree only +\let\doll\relax +\ifwasinsideprooftree +\then \let\VBOX\vbox +\else \ifmmode\else$\let\doll=$\fi + \let\VBOX\vcenter +\fi +% this \vbox or \vcenter is the actual output: +\VBOX {\baselineskip\proofrulebaseline \lineskip.2ex + \expandafter\lineskiplimit\ifproofdots0ex\else-0.6ex\fi + \hbox spread\dimen5 {\hfi\unhbox\proofabove\hfi}% + \hbox{\box0}% + \hbox {\kern\dimen2 \box\proofbelow}}\doll% +% +% pass new indentations out of scope +\global\dimen2=\dimen2 +\global\dimen3=\dimen3 +\egroup % NESTED ZERO +\ifonleftofproofrule +\then \shortenproofleft=\dimen2 +\fi +\shortenproofright=\dimen3 +% +% some space on right and flag we've just made a tree +\onleftofproofrulefalse +\ifinsideprooftree +\then \hskip.5em plus 1fil \penalty2 +\fi +} + +%========================================================================== +% IDEAS +% 1. Specification of \shiftright and how to spread trees. +% 2. Spacing command \m which causes 1em+1fil spacing, over-riding +% exisiting space on sides of trees and not affecting the +% detection of being on the left or right. +% 3. Hack using \@currenvir to detect LaTeX environment; have to +% use \aftergroup to pass \shortenproofleft/right out. +% 4. (Pie in the sky) detect how much trees can be "tucked in" +% 5. Discharged hypotheses (diagonal lines). diff --git a/document/root.bib b/document/root.bib new file mode 100644 index 0000000..b29d8d9 --- /dev/null +++ b/document/root.bib @@ -0,0 +1,1384 @@ +% $Id: adb-long.bib 7880 2012-01-06 17:38:24Z brucker $ +@PREAMBLE{ {\providecommand{\ac}[1]{\textsc{#1}} } + # {\providecommand{\acs}[1]{\textsc{#1}} } + # {\providecommand{\acf}[1]{\textsc{#1}} } + # {\providecommand{\TAP}{T\kern-.1em\lower-.5ex\hbox{A}\kern-.1em P} } + # {\providecommand{\leanTAP}{\mbox{\sf lean\it\TAP}} } + # {\providecommand{\holz}{\textsc{hol-z}} } + # {\providecommand{\holocl}{\textsc{hol-ocl}} } + # {\providecommand{\isbn}{\textsc{isbn}} } + # {\providecommand{\Cpp}{C++} } + # {\providecommand{\Specsharp}{Spec\#} } + # {\providecommand{\doi}[1]{\href{http://dx.doi.org/#1}{doi: + {\urlstyle{rm}\nolinkurl{#1}}}}} } +@STRING{conf-tphols="{TPHOLs}" } +@STRING{iso = {International Organization for Standardization} } +@STRING{j-ar = "Journal of Automated Reasoning" } +@STRING{j-cacm = "Communications of the {ACM}" } +@STRING{j-acta-informatica = "Acta Informatica" } +@STRING{j-sosym = "Software and Systems Modeling" } +@STRING{j-sttt = "International Journal on Software Tools for Technology (STTT)" } +@STRING{j-ist = "Information and Software Technology" } +@STRING{j-toplas= "{ACM} Transactions on Programming Languages and + Systems" } +@STRING{j-tosem = "{ACM} Transactions on Software Engineering and + Methodology" } +@STRING{j-eceasst="Electronic Communications of the {EASST}" } +@STRING{j-fac = "Formal Aspects of Computing (FAC)" } +@STRING{j-ucs = "Journal of Universal Computer Science" } +@STRING{j-sl = "Journal of Symbolic Logic" } +@STRING{j-fp = "Journal of Functional Programming" } +@STRING{j-tkde = {{IEEE} Transaction on Knowledge and Data Engineering} } +@STRING{j-tse = {{IEEE} Transaction on Software Engineering} } +@STRING{j-entcs = {Electronic Notes in Theoretical Computer Science} } +@STRING{s-lni = "Lecture Notes in Informatics" } +@STRING{s-lnai = "Lecture Notes in Computer Science" } +@STRING{s-lncs = "Lecture Notes in Computer Science" } +@STRING{s-lnbip = "Lecture Notes in Business Information Processing" } +@String{j-computer = "Computer"} +@String{j-tissec = "{ACM} Transactions on Information and System Security"} +@STRING{omg = {Object Management Group} } +@STRING{j-ipl = {Information Processing Letters} } +@STRING{j-login = ";login: the USENIX Association newsletter" } + +@STRING{PROC = "Proceedings of the " } +@String{j-nams = "Notices of the American Mathematical + Society"} +@String{j-jucs = "Journal of Universal Computer Science"} +@String{j-acm = "Journal of the ACM (JACM)"} + + +% Conferences +% ============ +@STRING{conf-sacmat = "ACM symposium on access control models and + technologies (SACMAT)"} +@STRING{conf-policy = "IEEE International Symposium on Policies for Distributed + Systems and Networks (POLICY)"} + +% Publisher: +% ========== +@STRING{pub-awl = {Addison-Wesley Longman, Inc.} } +@STRING{pub-awl:adr={Reading, MA, {USA}} } +@STRING{pub-springer={Springer-Verlag} } +@STRING{pub-springer:adr={Heidelberg} } +@STRING{pub-cup = {Cambridge University Press} } +@STRING{pub-cup:adr={New York, {NY}, {USA}} } +@STRING{pub-mit = {{MIT} Press} } +@STRING{pub-mit:adr={Cambridge, Massachusetts} } +@STRING{pub-springer-ny={Springer-Verlag} } +, +@STRING{pub-springer-netherlands={Springer Netherlands} } +@STRING{pub-springer-netherlands:adr={} } +@STRING{pub-springer-ny:adr={New York, {NY}, {USA}} } +@STRING{pub-springer-london={Springer-Verlag} } +@STRING{pub-springer-london:adr={London} } +@STRING{pub-ieee= {{IEEE} Computer Society} } +@STRING{pub-ieee:adr={Los Alamitos, {CA}, {USA}} } +@STRING{pub-prentice={Prentice Hall, Inc.} } +@STRING{pub-prentice:adr={Upper Saddle River, {NJ}, {USA}} } +@STRING{pub-acm = {{ACM} Press} } +@STRING{pub-acm:adr={New York, {NY} {USA}} } +@STRING{pub-oxford={Oxford University Press, Inc.} } +@STRING{pub-oxford:adr={New York, {NY}, {USA}} } +@STRING{pub-kluwer={Kluwer Academic Publishers} } +@STRING{pub-kluwer:adr={Dordrecht} } +@STRING{pub-elsevier={Elsevier Science Publishers} } +@STRING{pub-elsevier:adr={Amsterdam} } +@STRING{pub-north={North-Holland Publishing Co.} } +@STRING{pub-north:adr={Nijmegen, The Netherlands} } +@STRING{pub-ios = {\textsc{ios} Press} } +@STRING{pub-ios:adr={Amsterdam, The Netherlands} } +@STRING{pub-heise={Heise Zeitschriften Verlag} } +@STRING{pub-heise:adr={Hannover, Germany} } +@STRING{pub-wiley={John Wiley \& Sons} } +@STRING{pub-wiley:adr={} } + +@Book{ andrews:introduction:2002, + author = {Peter B. Andrews}, + title = {Introduction to Mathematical Logic and Type Theory: To + Truth through Proof}, + year = 2002, + isbn = {1-402-00763-9}, + edition = {2nd}, + publisher = pub-kluwer, + address = pub-kluwer:adr, + acknowledgement={brucker, 2007-04-23}, + bibkey = {andrews:introduction:2002} +} + +@InProceedings{ barnett.ea:spec:2004, + author = {Mike Barnett and K. Rustan M. Leino and Wolfram Schulte}, + abstract = "Spec# is the latest in a long line of work on programming + languages and systems aimed at improving the development of + correct software. This paper describes the goals and + architecture of the Spec# programming system, consisting of + the object-oriented Spec# programming language, the Spec# + compiler, and the Boogie static program verifier. The + language includes constructs for writing specifications + that capture programmer intentions about how methods and + data are to be used, the compiler emits run-time checks to + enforce these specifications, and the verifier can check + the consistency between a program and its specifications.", + language = {USenglish}, + title = {The {\Specsharp} programming system: An overview}, + pages = {49--69}, + crossref = {barthe.ea:construction:2005}, + bibkey = {barnett.ea:spec:2004}, + doi = {10.1007/b105030}, + acknowledgement={brucker, 2007-02-19}, + month = may # {~25} +} + +@InProceedings{ barrett.ea:cvc3:2007, + author = {Clark Barrett and Cesare Tinelli}, + title = {CVC3}, + booktitle = {CAV}, + year = 2007, + pages = {298--302}, + doi = {10.1007/978-3-540-73368-3_34}, + crossref = {damm.ea:computer:2007} +} + +@Proceedings{ barthe.ea:construction:2005, + editor = {Gilles Barthe and Lilian Burdy and Marieke Huisman and + Jean-Louis Lanet and Traian Muntean}, + title = {Construction and Analysis of Safe, Secure, and + Interoperable Smart Devices ({CASSIS})}, + booktitle = {Construction and Analysis of Safe, Secure, and + Interoperable Smart Devices ({CASSIS})}, + publisher = pub-springer, + address = pub-springer:adr, + series = s-lncs, + volume = 3362, + year = 2005, + isbn = {978-3-540-24287-1}, + acknowledgement={brucker, 2007-02-19}, + doi = {10.1007/b105030} +} + +@Proceedings{ bezivin.ea:unified:1999, + editor = {Jean B{\'e}zivin and Pierre-Alain Muller}, + doi = {10.1007/b72309}, + booktitle = {The Unified Modeling Language. \guillemotleft + {UML}\guillemotright'98: Beyond the Notation}, + title = {The Unified Modeling Language. \guillemotleft + {UML}\guillemotright'98: Beyond the Notation}, + publisher = pub-springer, + address = pub-springer:adr, + acknowledgement={brucker, 2007-04-23}, + series = s-lncs, + volume = 1618, + year = 1999, + isbn = {3-540-66252-9} +} + +@InProceedings{ blanchette.ea:nitpick:2010, + author = {Jasmin Christian Blanchette and Tobias Nipkow}, + title = {Nitpick: A Counterexample Generator for Higher-Order Logic + Based on a Relational Model Finder}, + booktitle = {ITP}, + year = 2010, + pages = {131--146}, + doi = {10.1007/978-3-642-14052-5_11}, + crossref = {kaufmann.ea:interactive:2010} +} + +@Article{ church:types:1940, + author = {Church, Alonzo}, + title = {A formulation of the simple theory of types}, + journal = j-sl, + year = 1940, + volume = 5, + number = 2, + month = jun, + pages = {56--68}, + acknowledgement={brucker, 2007-04-23}, + bibkey = {church:types:1940} +} + +@InProceedings{ cook.ea::amsterdam:2002, + abstract = {In November 1998 the authors participated in a two-day + workshop on the Object Constraint Language (OCL) in + Amsterdam. The focus was to clarify issues about the + semantics and the use of OCL, and to discuss useful and + necessary extensions of OCL. Various topics have been + raised and clarified. This manifesto contains the results + of that workshop and the following work on these topics. + Overview of OCL.}, + author = {Steve Cook and Anneke Kleppe and Richard Mitchell and + Bernhard Rumpe and Jos Warmer and Alan Wills}, + title = {The Amsterdam Manifesto on {OCL}}, + pages = {115--149}, + crossref = {clark.ea:object:2002}, + acknowledgement={brucker, 2007-02-19}, + tags = {MDE}, + clearance = {unclassified}, + timestap = {2008-05-26} +} + +@Proceedings{ damm.ea:computer:2007, + editor = {Werner Damm and Holger Hermanns}, + title = {Computer Aided Verification, 19th International + Conference, CAV 2007, Berlin, Germany, July 3-7, 2007, + Proceedings}, + booktitle = {CAV}, + publisher = pub-springer, + series = s-lncs, + volume = 4590, + year = 2007, + isbn = {978-3-540-73367-6} +} + +@InProceedings{ gogolla.ea:expressing:2001, + author = {Martin Gogolla and Mark Richters}, + bibkey = {gogolla.ea:expressing:2001}, + abstract = {The Unified Modeling Language {UML} is a complex + language offering many modeling features. Especially the + description of static structures with class diagrams is + supported by a rich set of primitives. This paper shows how + to transfrom {UML} class diagrams involving cardinality + constraints, qualifiers, association classes, aggregations, + compositions, and generalizations into equivalent {UML} + class diagrams employing only binary associations and + {OCL} constraints. Thus we provide a better + understanding of {UML} features. By reducing more + complex features in terms of basic ones, we suggest an easy + way users can gradually extend the set of {UML} + elements they commonly apply in the modeling process.}, + title = {Expressing {UML} Class Diagrams Properties with + {OCL}}, + pages = {85--114}, + crossref = {clark.ea:object:2002}, + acknowledgement={brucker, 2007-02-19}, + tags = {MDE}, + clearance = {unclassified}, + timestap = {2008-05-26} +} + +@Proceedings{ clark.ea:object:2002, + editor = {Tony Clark and Jos Warmer}, + booktitle = {Object Modeling with the {OCL}: The Rationale behind + the Object Constraint Language}, + title = {Object Modeling with the {OCL}: The Rationale behind + the Object Constraint Language}, + publisher = pub-springer, + address = pub-springer:adr, + series = s-lncs, + volume = 2263, + year = 2002, + isbn = {3-540-43169-1}, + acknowledgement={brucker, 2007-02-19}, + tags = {MDE}, + clearance = {unclassified}, + timestap = {2008-05-26} +} + +@Proceedings{ grumberg.ea:tools:2007, + editor = {Orna Grumberg and Michael Huth}, + title = {Tools and Algorithms for the Construction and Analysis of + Systems, 13th International Conference, TACAS 2007, Held as + Part of the Joint European Conferences on Theory and + Practice of Software, ETAPS 2007 Braga, Portugal, March 24 + - April 1, 2007, Proceedings}, + booktitle = {TACAS}, + publisher = pub-springer, + address = pub-springer:adr, + series = s-lncs, + volume = 4424, + year = 2007, + isbn = {978-3-540-71208-4} +} + +@InProceedings{ hamie.ea:reflections:1998, + bibkey = {hamie.ea:reflections:1998}, + author = {Ali Hamie and Franco Civello and John Howse and Stuart + Kent and Richard Mitchell}, + title = {{Reflections on the Object Constraint Language}}, + year = 1998, + doi = {10.1007/b72309}, + topic = {formalism}, + acknowledgement={brucker, 2007-04-23}, + pages = {162--172}, + crossref = {bezivin.ea:unified:1999}, + abstract = {The \acf{ocl}, which forms part of the {UML} set of + modelling notations, is a precise, textual language for + expressing constraints that cannot be shown + diagrammatically in {UML}. This paper reflects on a + number of aspects of the syntax and semantics of the + {OCL}, and makes proposals for clarification or + extension. Specifically, the paper suggests that: the + concept of flattening collections of collections is + unnecessary, state models should be connectable to class + models, defining object creation should be made more + convenient, {OCL} should be based on a 2-valued logic, + set subtraction should be covered more fully, and a "let" + feature should be introduced. } +} + +@Proceedings{ kaufmann.ea:interactive:2010, + editor = {Matt Kaufmann and Lawrence C. Paulson}, + title = {Interactive Theorem Proving, First International + Conference, ITP 2010, Edinburgh, UK, July 11-14, 2010. + Proceedings}, + booktitle = {ITP}, + publisher = pub-springer, + series = s-lncs, + volume = 6172, + year = 2010, + isbn = {978-3-642-14051-8}, + doi = {10.1007/978-3-642-14052-5} +} + +@InProceedings{ kosiuczenko:specification:2006, + author = {Piotr Kosiuczenko}, + title = {Specification of Invariability in {OCL}}, + pages = {676--691}, + doi = {10.1007/11880240_47}, + crossref = {nierstrasz.ea:model:2006}, + abstract = {The paradigm of contractual specification provides a + transparent way of specifying systems. It clearly + distinguishes between client and implementer obligations. + One of the best known languages used for this purpose is + OCL. Nevertheless, OCL does not provide primitives for a + compact specification of what remains unchanged when a + method is executed. In this paper, problems with specifying + invariability are listed and some weaknesses of existing + solutions are pointed out. The question of specifying + invariability in OCL is studied and a simple but expressive + and flexible extension is proposed. It is shown that this + extension has a simple OCL based semantics.} +} + +@InProceedings{ krieger.ea:generative:2010, + author = {Matthias P. Krieger and Alexander Knapp and Burkhart + Wolff}, + title = {Generative Programming and Component Engineering}, + booktitle = {International Conference on Generative Programming and + Component Engineering (GPCE 2010)}, + month = oct, + location = {Eindhoven, The Netherlands, October 10-13, 2010}, + year = 2010, + pages = {53--62}, + ee = {http://doi.acm.org/10.1145/1868294.1868303}, + editor = {Eelco Visser and Jaakko J{\"a}rvi}, + publisher = {ACM}, + isbn = {978-1-4503-0154-1}, + abstract = {Operation contracts consisting of pre- and postconditions + are a well-known means of specifying operations. In this + paper we deal with the problem of operation contract + simulation, i.e., determining operation results satisfying + the postconditions based on input data supplied by the + user; simulating operation contracts is an important + technique for requirements validation and prototyping. + Current approaches to operation contract simulation exhibit + poor performance for large sets of input data or require + additional guidance from the user. We show how these + problems can be alleviated and describe an efficient as + well as fully automatic approach. It is implemented in our + tool OCLexec that generates from UML/OCL operation + contracts corresponding Java implementations which call a + constraint solver at runtime. The generated code can serve + as a prototype. A case study demonstrates that our approach + can handle problem instances of considerable size.} +} + +@InProceedings{ mandel.ea:ocl:1999, + author = {Luis Mandel and Mar{\`i}a Victoria Cengarle}, + bibkey = {mandel.ea:ocl:1999}, + language = {USenglish}, + topic = {formalism}, + public = {yes}, + title = {On the expressive power of {{OCL}}}, + acknowledgement={brucker, 2007-04-23}, + timestamp = 962971498, + abstract = {This paper examines the expressive power of {OCL} in + terms of navigability and computability. First the + expressive power of {OCL} is compared with the + relational calculus; it is showed that {OCL} is not + equivalent to the relational calculus. Then an algorithm + computing the transitive closure of a binary relation + operation that cannot be encoded in the relational calculus + is expressed in {OCL}. Finally the equivalence of + {OCL} with a Turing machine is pondered.}, + pages = {854--874}, + crossref = {wing.ea:world:1999}, + ee = {http://link.springer.de/link/service/series/0558/bibs/1708/17080854.htm} + +} + +@InProceedings{ moura.ea:z3:2008, + author = {Leonardo Mendon\c{c}a de Moura and Nikolaj Bj{\o}rner}, + title = {Z3: An Efficient {SMT} Solver}, + booktitle = {TACAS}, + year = 2008, + pages = {337--340}, + doi = {10.1007/978-3-540-78800-3_24}, + abstract = {Satisfiability Modulo Theories (SMT) problem is a decision + problem for logical first order formulas with respect to + combinations of background theories such as: arithmetic, + bit-vectors, arrays, and uninterpreted functions. Z3 is a + new and efficient SMT Solver freely available from + Microsoft Research. It is used in various software + verification and analysis applications. }, + crossref = {ramakrishnan.ea:tools:2008} +} + +@Proceedings{ nierstrasz.ea:model:2006, + editor = {Oscar Nierstrasz and Jon Whittle and David Harel and + Gianna Reggio}, + title = {Model Driven Engineering Languages and Systems + ({MoDELS})}, + booktitle = {Model Driven Engineering Languages and Systems + ({MoDELS})}, + address = pub-springer:adr, + location = {Genova, Italy}, + publisher = pub-springer, + series = s-lncs, + acknowledgement={brucker, 2007-02-19}, + volume = 4199, + year = 2006, + doi = {10.1007/11880240}, + isbn = {978-3-540-45772-5} +} + +@Book{ nipkow.ea:isabelle:2002, + author = {Tobias Nipkow and Lawrence C. Paulson and Markus Wenzel}, + title = {Isabelle/{HOL}---A Proof Assistant for Higher-Order + Logic}, + publisher = pub-springer, + address = pub-springer:adr, + series = s-lncs, + volume = 2283, + doi = {10.1007/3-540-45949-9}, + abstract = {This book is a self-contained introduction to interactive + proof in higher-order logic ({HOL}), using the proof + assistant Isabelle2002. It is a tutorial for potential + users rather than a monograph for researchers. The book has + three parts. + + 1. Elementary Techniques shows how to model functional + programs in higher-order logic. Early examples involve + lists and the natural numbers. Most proofs are two steps + long, consisting of induction on a chosen variable followed + by the auto tactic. But even this elementary part covers + such advanced topics as nested and mutual recursion. 2. + Logic and Sets presents a collection of lower-level tactics + that you can use to apply rules selectively. It also + describes Isabelle/{HOL}'s treatment of sets, functions + and relations and explains how to define sets inductively. + One of the examples concerns the theory of model checking, + and another is drawn from a classic textbook on formal + languages. 3. Advanced Material describes a variety of + other topics. Among these are the real numbers, records and + overloading. Advanced techniques are described involving + induction and recursion. A whole chapter is devoted to an + extended example: the verification of a security protocol. }, + year = 2002, + acknowledgement={brucker, 2007-02-19}, + bibkey = {nipkow.ea:isabelle:2002}, + tags = {noTAG}, + clearance = {unclassified}, + timestap = {2008-05-26} +} + +@Booklet{ omg:ocl:1997, + bibkey = {omg:ocl:1997}, + key = omg, + abstract = {This document introduces and defines the Object Constraint + Language ({OCL}), a formal language to express side + effect-free constraints. Users of the Unified Modeling + Language and other languages can use {OCL} to specify + constraints and other expressions attached to their models. + {OCL} was used in the {UML} Semantics document to + specify the well-formedness rules of the {UML} + metamodel. Each well-formedness rule in the static + semantics sections in the {UML} Semantics document + contains an {OCL} expression, which is an invariant for + the involved class. The grammar for {OCL} is specified + at the end of this document. A parser generated from this + grammar has correctly parsed all the constraints in the + {UML} Semantics document, a process which improved the + correctness of the specifications for {OCL} and {UML}.}, + institution = omg, + language = {USenglish}, + month = sep, + note = {Available as {OMG} document + \href{http://www.omg.org/cgi-bin/doc?ad/97-08-08} + {ad/97-08-08}}, + keywords = {{UML}, OCL}, + topic = {formalism}, + public = {yes}, + title = {Object Constraint Language Specification (Version 1.1)}, + year = 1997, + acknowledgement={brucker, 2007-04-23} +} + +@Booklet{ omg:ocl:2003, + bibkey = {omg:ocl:2003}, + key = omg, + abstract = {This document introduces and defines the Object Constraint + Language (OCL), a formal language to express side + effect-free constraints. Users of the Unified Modeling + Language and other languages can use OCL to specify + constraints and other expressions attached to their models. + OCL was used in the {UML} Semantics document to specify + the well-formedness rules of the {UML} metamodel. Each + well-formedness rule in the static semantics sections in + the {UML} Semantics document contains an OCL + expression, which is an invariant for the involved class. + The grammar for OCL is specified at the end of this + document. A parser generated from this grammar has + correctly parsed all the constraints in the {UML} + Semantics document, a process which improved the + correctness of the specifications for OCL and {UML}.}, + publisher = omg, + language = {USenglish}, + month = oct, + keywords = {{UML}, OCL}, + topic = {formalism}, + public = {yes}, + note = {Available as {OMG} document + \href{http://www.omg.org/cgi-bin/doc?ptc/03-10-14} + {ptc/03-10-14}}, + title = {{UML} 2.0 {OCL} Specification}, + year = 2003, + acknowledgement={brucker, 2007-04-23} +} + +@Booklet{ omg:ocl:2006, + bibkey = {omg:ocl:2006}, + key = omg, + abstract = {This document introduces and defines the Object Constraint + Language (OCL), a formal language to express side + effect-free constraints. Users of the Unified Modeling + Language and other languages can use OCL to specify + constraints and other expressions attached to their models. + OCL was used in the {UML} Semantics document to specify + the well-formedness rules of the {UML} metamodel. Each + well-formedness rule in the static semantics sections in + the {UML} Semantics document contains an OCL + expression, which is an invariant for the involved class. + The grammar for OCL is specified at the end of this + document. A parser generated from this grammar has + correctly parsed all the constraints in the {UML} + Semantics document, a process which improved the + correctness of the specifications for OCL and {UML}.}, + publisher = omg, + language = {USenglish}, + month = apr, + keywords = {{UML}, OCL}, + topic = {formalism}, + note = {Available as {OMG} document + \href{http://www.omg.org/cgi-bin/doc?formal/06-05-01} + {formal/06-05-01}}, + public = {yes}, + title = {{UML} 2.0 {OCL} Specification}, + year = 2006, + acknowledgement={brucker, 2007-04-23} +} + +@Booklet{ omg:ocl:2012, + bibkey = {omg:ocl:2012}, + key = omg, + abstract = {This document introduces and defines the Object Constraint + Language (OCL), a formal language to express side + effect-free constraints. Users of the Unified Modeling + Language and other languages can use OCL to specify + constraints and other expressions attached to their models. + OCL was used in the {UML} Semantics document to specify + the well-formedness rules of the {UML} metamodel. Each + well-formedness rule in the static semantics sections in + the {UML} Semantics document contains an OCL + expression, which is an invariant for the involved class. + The grammar for OCL is specified at the end of this + document. A parser generated from this grammar has + correctly parsed all the constraints in the {UML} + Semantics document, a process which improved the + correctness of the specifications for OCL and {UML}.}, + publisher = omg, + language = {USenglish}, + month = feb, + keywords = {{UML}, OCL}, + topic = {formalism}, + note = {Available as {OMG} document + \href{http://www.omg.org/cgi-bin/doc?formal/2012-01-01} + {formal/2012-01-01}}, + public = {yes}, + title = {{UML} 2.3.1 {OCL} Specification}, + year = 2012, + acknowledgement={brucker, 2012-08-01} +} + +@Booklet{ omg:uml-infrastructure:2011, + key = omg, + abstract = {}, + publisher = omg, + language = {USenglish}, + month = aug, + year = 2011, + note = {Available as {OMG} document + \href{http://www.omg.org/cgi-bin/doc?formal/2011-08-05} + {formal/2011-08-05}}, + keywords = {}, + topic = {}, + public = {yes}, + title = {{UML} 2.4.1: Infrastructure Specification} +} + +@Booklet{ omg:uml-superstructure:2011, + key = omg, + abstract = {}, + publisher = omg, + language = {USenglish}, + month = aug, + year = 2011, + note = {Available as {OMG} document + \href{http://www.omg.org/cgi-bin/doc?formal/2011-08-06} + {formal/2011-08-06}}, + keywords = {}, + topic = {}, + public = {yes}, + title = {{UML} 2.4.1: Superstructure Specification} +} + +@Proceedings{ ramakrishnan.ea:tools:2008, + editor = {C. R. Ramakrishnan and Jakob Rehof}, + title = {Tools and Algorithms for the Construction and Analysis of + Systems, 14th International Conference, TACAS 2008, Held as + Part of the Joint European Conferences on Theory and + Practice of Software, ETAPS 2008, Budapest, Hungary, March + 29-April 6, 2008. Proceedings}, + booktitle = {TACAS}, + publisher = pub-springer, + address = pub-springer:adr, + series = s-lncs, + volume = 4963, + year = 2008, + isbn = {978-3-540-78799-0} +} + +@PhDThesis{ richters:precise:2002, + author = {Mark Richters}, + title = {A Precise Approach to Validating {{UML}} Models and + {{OCL}} Constraints}, + school = {Universit{\"a}t Bremen}, + year = 2002, + address = {Logos Verlag, Berlin, {BISS} Monographs, No. 14}, + isbn = {3-89722-842-4}, + abstract = {We present a precise approach that allows an analysis and + validation of {UML} models and OCL constraints. We + focus on models and constraints specified in the analysis + and early design stage of a software development process. + For this purpose, a suitable subset of {UML} + corresponding to information that is usually represented in + class diagrams is identified and formally defined. This + basic modeling language provides a context for all OCL + constraints. We define a formal syntax and semantics of OCL + types, operations, expressions, invariants, and + pre-/postconditions. We also give solutions for problems + with the current OCL definition and discuss possible + extensions. A metamodel for OCL is introduced that defines + the abstract syntax of OCL expressions and the structure of + types and values. The metamodel approach allows a seamless + integration with the {UML} metamodeling architecture + and makes the benefits of a precise OCL definition easier + accessible. The OCL metamodel also allows to define + context-sensitive conditions for well-formed OCL + expressions more precisely. These conditions can now be + specified with OCL whereas they previously were specified + only informally. In order to demonstrate the practical + applicability of our work, we have realized substantial + parts of it in a tool supporting the validation of models + and constraints. Design specifications can be ``executed'' + and animated thus providing early feedback in an iterative + development process. Our approach offers novel ways for + checking user data against specifications, for automating + test procedures, and for checking CASE tools for standards + conformance. Therefore, this work contributes to the goal + of improving the overall quality of software systems by + combining theoretical and practical techniques.}, + acknowledgement={brucker, 2007-04-23} +} + +@InProceedings{ torlak.ea:kodkod:2007, + author = {Emina Torlak and Daniel Jackson}, + title = {Kodkod: A Relational Model Finder}, + booktitle = {TACAS}, + year = 2007, + pages = {632--647}, + doi = {10.1007/978-3-540-71209-1_49}, + crossref = {grumberg.ea:tools:2007}, + abstract = {The key design challenges in the construction of a + SAT-based relational model finder are described, and novel + techniques are proposed to address them. An efficient model + finder must have a mechanism for specifying partial + solutions, an effective symmetry detection and breaking + scheme, and an economical translation from relational to + boolean logic. These desiderata are addressed with three + new techniques: a symmetry detection algorithm that works + in the presence of partial solutions, a sparse-matrix + representation of relations, and a compact representation + of boolean formulas inspired by boolean expression diagrams + and reduced boolean circuits. The presented techniques have + been implemented and evaluated, with promising results.} +} + +@InCollection{ wenzel.ea:building:2007, + abstract = {We present the generic system framework of + Isabelle/Isarunderlying recent versions of Isabelle. Among + other things, Isar provides an infrastructure for Isabelle + plug-ins, comprising extensible state components and + extensible syntax that can be bound to tactical ML + programs. Thus the Isabelle/Isar architecture may be + understood as an extension and refinement of the + traditional LCF approach, with explicit infrastructure for + building derivative systems. To demonstrate the technical + potential of the framework, we apply it to a concrete + formalmethods tool: the HOL-Z 3.0 environment, which is + geared towards the analysis of Z specifications and formal + proof of forward-refinements.}, + author = {Makarius Wenzel and Burkhart Wolff}, + booktitle = {{TPHOLs} 2007}, + editor = {Klaus Schneider and Jens Brandt}, + language = {USenglish}, + acknowledgement={none}, + pages = {352--367}, + publisher = pub-springer, + address = pub-springer:adr, + number = 4732, + series = s-lncs, + title = {Building Formal Method Tools in the {Isabelle}/{Isar} + Framework}, + doi = {10.1007/978-3-540-74591-4_26}, + year = 2007 +} + +@PhDThesis{ wenzel:isabelleisar:2002, + author = {Markus M. Wenzel}, + title = {Isabelle/Isar --- a versatile environment for + human-readable formal proof documents}, + school = {TU M{\"u}nchen}, + year = 2002, + url = {http://tumb1.biblio.tu-muenchen.de/publ/diss/in/2002/wenzel.html} + , + abstract = {The basic motivation of this work is to make formal theory + developments with machine-checked proofs accessible to a + broader audience. Our particular approach is centered + around the Isar formal proof language that is intended to + support adequate composition of proof documents that are + suitable for human consumption. Such primary proofs written + in Isar may be both checked by the machine and read by + human-beings; final presentation merely involves trivial + pretty printing of the sources. Sound logical foundations + of Isar are achieved by interpretation within the generic + Natural Deduction framework of Isabelle, reducing all + high-level reasoning steps to primitive inferences. + + The resulting Isabelle/Isar system is generic with respect + to object-logics and proof tools, just as pure Isabelle + itself. The full Isar language emerges from a small core by + means of several derived elements, which may be combined + freely with existing ones. This results in a very rich + space of expressions of formal reasoning, supporting many + viable proof techniques. The general paradigms of Natural + Deduction and Calculational Reasoning are both covered + particularly well. Concrete examples from logic, + mathematics, and computer-science demonstrate that the Isar + concepts are indeed sufficiently versatile to cover a broad + range of applications.}, + address = {M{\"u}nchen}, + month = feb, + acknowledgement={none}, + bibkey = {wenzel:isabelleisar:2002} +} + +@Proceedings{ wing.ea:world:1999, + editor = {Jeannette M. Wing and Jim Woodcock and Jim Davies}, + booktitle = {World Congress on Formal Methods in the Development of + Computing Systems (FM)}, + title = {World Congress on Formal Methods in the Development of + Computing Systems (FM)}, + publisher = pub-springer, + address = pub-springer:adr, + acknowledgement={brucker, 2007-04-23}, + series = s-lncs, + volume = 1708, + year = 1999, + isbn = {3-540-66587-0} +} +@Proceedings{ bezivin.ea:unified:1999, + editor = {Jean B{\'e}zivin and Pierre-Alain Muller}, + doi = {10.1007/b72309}, + booktitle = {The Unified Modeling Language. \guillemotleft + {UML}\guillemotright'98: Beyond the Notation}, + title = {The Unified Modeling Language. \guillemotleft + {UML}\guillemotright'98: Beyond the Notation}, + publisher = pub-springer, + address = pub-springer:adr, + acknowledgement={brucker, 2007-04-23}, + series = s-lncs, + volume = 1618, + year = 1999, + isbn = {3-540-66252-9} +} + +@Proceedings{ grumberg.ea:tools:2007, + editor = {Orna Grumberg and Michael Huth}, + title = {Tools and Algorithms for the Construction and Analysis of + Systems, 13th International Conference, TACAS 2007, Held as + Part of the Joint European Conferences on Theory and + Practice of Software, ETAPS 2007 Braga, Portugal, March 24 + - April 1, 2007, Proceedings}, + booktitle = {TACAS}, + publisher = pub-springer, + address = pub-springer:adr, + series = s-lncs, + volume = 4424, + year = 2007, + isbn = {978-3-540-71208-4} +} + + +@Article{ brucker.ea:semantic:2006-b, + abstract = {We report on the results of a long-term project to + formalize the semantics of OCL 2.0 in Higher-order Logic + (HOL). The ultimate goal of the project is to provide a + formalized, machine-checked semantic basis for a theorem + proving environment for OCL (as an example for an + object-oriented specification formalism) which is as + faithful as possible to the original informal semantics. We + report on various (minor) inconsistencies of the OCL + semantics, discuss the more recent attempt to align the OCL + semantics with UML 2.0 and suggest several extensions which + make, in our view, OCL semantics more fit for future + extensions towards programming-like verifications and + specification refinement, which are, in our view, necessary + to make OCL more fit for future extensions. }, + author = {Achim D. Brucker and J\"urgen Doser and Burkhart Wolff}, + language = {USenglish}, + public = {yes}, + categories = {holocl}, + classification= {workshop}, + areas = {formal methods, software}, + keywords = {HOL-OCL, UML/OCL, formal semantics}, + title = {Semantic Issues of {OCL}: Past, Present, and Future}, + editor = {Birgith Demuth and Dan Chiorean and Martin Gogolla and Jos + Warmer}, + issn = {1863-2122}, + volume = {5}, + year = {2006}, + journal = {Electronic Communications of the EASST}, + copyright = {ECEASST}, + copyrighturl = {http://eceasst.cs.tu-berlin.de/index.php/eceasst/article/view/46} + , + pdf = {http://www.brucker.ch/bibliography/download/2006/brucker.ea-semantic-2006-b.pdf}, + url = {http://www.brucker.ch/bibliography/abstract/brucker.ea-semantic-2006-b} + +} + +@InCollection{ brucker.ea:proposal:2002, + abstract = {We present a formal semantics as a conservative shallow + embedding of the Object Constraint Language (OCL). OCL is + currently under development within an open standardization + process within the OMG; our work is an attempt to accompany + this process by a proposal solving open questions in a + consistent way and exploring alternatives of the language + design. Moreover, our encoding gives the foundation for + tool supported reasoning over OCL specifications, for + example as basis for test case generation.}, + keywords = {Isabelle, OCL, UML, shallow embedding, testing}, + location = {Hampton, VA, USA}, + author = {Achim D. Brucker and Burkhart Wolff}, + booktitle = {Theorem Proving in Higher Order Logics (TPHOLs)}, + editor = {V{\'\i}ctor A. Carre{\~n}o and C{\'e}sar A. Mu{\~n}oz and + Sophi{\`e}ne Tahar}, + language = {USenglish}, + pdf = {http://www.brucker.ch/bibliography/download/2002/brucker.ea-proposal-2002.pdf}, + filelabel = {Extended Version}, + file = {http://www.brucker.ch/bibliography/download/2002/ocl_semantic_extended.pdf}, + publisher = {Springer-Verlag}, + address = {Heidelberg}, + series = {Lecture Notes in Computer Science}, + number = {2410}, + pages = {99--114}, + project = {CSFMDOS}, + doi = {10.1007/3-540-45685-6_8}, + title = {A Proposal for a Formal {OCL} Semantics in + {Isabelle/HOL}}, + categories = {holocl}, + classification= {conference}, + areas = {formal methods, software}, + isbn = {3-540-44039-9}, + issn = {0302-9743}, + year = {2002}, + public = {yes}, + url = {http://www.brucker.ch/bibliography/abstract/brucker.ea-proposal-2002} + +} + +@InProceedings{ brucker.ea:summary-aachen:2013, + author = {Achim D. Brucker and Dan Chiorean and Tony Clark and + Birgit Demuth and Martin Gogolla and Dimitri Plotnikov and + Bernhard Rumpe and Edward D. Willink and Burkhart Wolff}, + title = {Report on the {Aachen} {OCL} Meeting}, + booktitle = {Proceedings of the MODELS 2013 OCL Workshop (OCL 2013)}, + location = {Miami, USA}, + editor = {Jordi Cabot and Martin Gogolla and Istvan Rath and Edward + Willink}, + publisher = {CEUR-WS.org}, + series = {CEUR Workshop Proceedings}, + volume = {1092}, + ee = {http://ceur-ws.org/Vol-1092}, + pages = {103--111}, + year = {2013}, + abstract = {As a continuation of the OCL workshop during the MODELS + 2013 conference in October 2013, a number of OCL experts + decided to meet in November 2013 in Aachen for two days to + discuss possible short term improvements of OCL for an + upcoming OMG meeting and to envision possible future + long-term developments of the language. This paper is a + sort of ``minutes of the meeting'' and intended to quickly + inform the OCL community about the discussion topics.}, + classification= {invited}, + categories = {holocl}, + areas = {software}, + public = {yes}, + pdf = {http://www.brucker.ch/bibliography/download/2013/brucker.ea-ocl-aachen-2013.pdf}, + url = {http://www.brucker.ch/bibliography/abstract/brucker.ea-summary-aachen-2013} + +} + +@InCollection{ brucker.ea:transformation:2006, + abstract = {SecureUML is a security modeling language for formalizing + access control requirements in a declarative way. It is + equipped with a UML notation in terms of a UML profile, + and can be combined with arbitrary design modeling + languages. We present a semantics for SecureUML in terms of + a model transformation to standard UML/OCL. The + transformation scheme is used as part of an implementation + of a tool chain ranging from front-end visual modeling + tools over code-generators to the interactive theorem + proving environment \holocl. The methodological + consequences for an analysis of the generated OCL formulae + are discussed.}, + keywords = {security, SecureUML, UML, OCL, HOL-OCL, + model-transformation}, + location = {Genova}, + author = {Achim D. Brucker and J\"urgen Doser and Burkhart Wolff}, + booktitle = {{MoDELS} 2006: Model Driven Engineering Languages and + Systems}, + language = {USenglish}, + publisher = {Springer-Verlag}, + talk = {talk:brucker.ea:transformation:2006}, + address = {Heidelberg}, + series = {Lecture Notes in Computer Science}, + doi = {10.1007/11880240_22}, + number = {4199}, + pages = {306--320}, + editor = {Oscar Nierstrasz and Jon Whittle and David Harel and + Gianna Reggio}, + project = {CSFMDOS}, + title = {A Model Transformation Semantics and Analysis Methodology + for {SecureUML}}, + categories = {holocl}, + classification= {conference}, + areas = {security, formal methods, software}, + file = {http://www.brucker.ch/bibliography/download/2006/brucker.ea-transformation-2006-b.pdf}, + filelabel = {Extended Version}, + year = {2006}, + public = {yes}, + pdf = {http://www.brucker.ch/bibliography/download/2006/brucker.ea-transformation-2006.pdf}, + note = {An extended version of this paper is available as ETH + Technical Report, no. 524.}, + url = {http://www.brucker.ch/bibliography/abstract/brucker.ea-transformation-2006} + +} + +@TechReport{ brucker.ea:hol-ocl-book:2006, + author = {Achim D. Brucker and Burkhart Wolff}, + institution = {ETH Zurich}, + language = {USenglish}, + title = {The {HOL-OCL} Book}, + classification= {unrefereed}, + areas = {formal methods, software}, + categories = {holocl}, + year = {2006}, + number = {525}, + abstract = {HOL-OCL is an interactive proof environment for the Object + Constraint Language (OCL). It is implemented as a shallow + embedding of OCL into the Higher-order Logic (HOL) instance + of the interactive theorem prover Isabelle. HOL-OCL defines + a machine-checked formalization of the semantics as + described in the standard for OCL 2.0. This conservative, + shallow embedding of UML/OCL into Isabelle/HOL includes + support for typed, extensible UML data models supporting + inheritance and subtyping inside the typed lambda-calculus + with parametric polymorphism. As a consequence of + conservativity with respect to higher-order logic (HOL), we + can guarantee the consistency of the semantic model. + Moreover, HOL-OCL provides several derived calculi for + UML/OCL that allow for formal derivations establishing the + validity of UML/OCL formulae. Elementary automated support + for such proofs is also provided top }, + bibkey = {brucker.ea:hol-ocl-book:2006}, + pdf = {http://www.brucker.ch/bibliography/download/2006/brucker.ea-hol-ocl-book-2006.pdf}, + keywords = {security, SecureUML, UML, OCL, HOL-OCL, + model-transformation}, + public = {yes}, + url = {http://www.brucker.ch/bibliography/abstract/brucker.ea-hol-ocl-book-2006} + +} + +@InCollection{ brucker.ea:hol-ocl:2008, + abstract = {We present the theorem proving environment HOL-OCL that is + integrated in a MDE framework. HOL-OCL allows to reason + over UMLclass models annotated with OCL specifications. + Thus, HOL-OCL strengthens a crucial part of the UML to an + object-oriented formal method. HOL-OCL provides several + derived proof calculi that allow for formal derivations + establishing the validity of UML/OCL formulae. These + formulae arise naturally when checking the consistency of + class models, when formally refining abstract models to + more concrete ones or when discharging side-conditions from + model-transformations.}, + keywords = {HOL-OCL, UML, OCL, Formal Methods, Theorem Proving, + Refinement}, + location = {Budapest, Hungary}, + author = {Achim D. Brucker and Burkhart Wolff}, + booktitle = {Fundamental Approaches to Software Engineering + {(FASE08)}}, + talk = {brucker.ea:hol-ocl:2008}, + language = {USenglish}, + publisher = {Springer-Verlag}, + address = {Heidelberg}, + series = {Lecture Notes in Computer Science}, + number = {4961}, + doi = {10.1007/978-3-540-78743-3_8}, + pages = {97--100}, + editor = {Jos{\'e} Fiadeiro and Paola Inverardi}, + title = {{HOL-OCL} -- {A Formal Proof Environment for + {UML}/{OCL}}}, + categories = {holocl}, + classification= {conference}, + areas = {formal methods, software}, + year = {2008}, + pdf = {http://www.brucker.ch/bibliography/download/2008/brucker.ea-hol-ocl-2008.pdf}, + public = {yes}, + url = {http://www.brucker.ch/bibliography/abstract/brucker.ea-hol-ocl-2008} + +} + +@PhDThesis{ brucker:interactive:2007, + author = {Achim D. Brucker}, + title = {An Interactive Proof Environment for Object-oriented + Specifications}, + school = {ETH Zurich}, + year = {2007}, + public = {yes}, + month = mar, + classification= {thesis}, + areas = {formal methods, software}, + categories = {holocl}, + keywords = {OCL, UML, formal semantics, theorem proving, Isabelle, + HOL-OCL}, + note = {ETH Dissertation No. 17097.}, + abstract = {We present a semantic framework for object-oriented + specification languages. We develop this framework as a + conservative shallow embedding in Isabelle/HOL. Using only + conservative extensions guarantees by construction the + consistency of our formalization. Moreover, we show how our + framework can be used to build an interactive proof + environment, called HOL-OCL, for object-oriented + specifications in general and for UML/OCL in particular. + + Our main contributions are an extensible encoding of + object-oriented data structures in HOL, a datatype package + for object-oriented specifications, and the development of + several equational and tableaux calculi for object-oriented + specifications. Further, we show that our formal framework + can be the basis of a formal machine-checked semantics for + OCL that is compliant to the OCL 2.0 standard. }, + abstract_de = {In dieser Arbeit wird ein semantisches Rahmenwerk f{\"u}r + objektorientierte Spezifikationen vorgestellt. Das + Rahmenwerk ist als konservative, flache Einbettung in + Isabelle/HOL realisiert. Durch die Beschr{\"a}nkung auf + konservative Erweiterungen kann die logische Konsistenz der + Einbettung garantiert werden. Das semantische Rahmenwerk + wird verwendet, um das interaktives Beweissystem HOL-OCL + f{\"u}r objektorientierte Spezifikationen im Allgemeinen + und insbesondere f{\"u}r UML/OCL zu entwickeln. + + Die Hauptbeitr{\"a}ge dieser Arbeit sind die Entwicklung + einer erweiterbaren Kodierung objektorientierter + Datenstrukturen in HOL, ein Datentyp-Paket f{\"u}r + objektorientierte Spezifikationen und die Entwicklung + verschiedener Kalk{\"u}le f{\"u}r objektorientierte + Spezifikationen. Zudem zeigen wir, wie das formale + Rahmenwerk verwendet werden kann, um eine formale, + maschinell gepr{\"u}fte Semantik f{\"u}r OCL anzugeben, die + konform zum Standard f{\"u}r OCL 2.0 ist.}, + pdf = {http://www.brucker.ch/bibliography/download/2007/brucker-interactive-2007.pdf}, + url = {http://www.brucker.ch/bibliography/abstract/brucker-interactive-2007} + +} + + +@Article{ brucker.ea:extensible:2008-b, + abstract = {We present an extensible encoding of object-oriented data + models into HOL. Our encoding is supported by a datatype + package that leverages the use of the shallow embedding + technique to object-oriented specification and programming + languages. The package incrementally compiles an + object-oriented data model, i.e., a class model, to a + theory containing object-universes, constructors, accessor + functions, coercions (casts) between dynamic and static + types, characteristic sets, and co-inductive class + invariants. The package is conservative, i.e., all + properties are derived entirely from constant definitions, + including the constraints over object structures. As an + application, we use the package for an object-oriented + core-language called IMP++, for which we formally prove the + correctness of a Hoare-Logic with respect to a denotational + semantics.}, + author = {Achim D. Brucker and Burkhart Wolff}, + language = {USenglish}, + public = {yes}, + classification= {journal}, + areas = {formal methods, software}, + keywords = {object-oriented data models, HOL, theorem proving, + verification}, + title = {An Extensible Encoding of Object-oriented Data Models in + HOL}, + year = {2008}, + journal = {Journal of Automated Reasoning}, + volume = {41}, + issue = {3}, + pages = {219--249}, + issn = {0168-7433}, + doi = {10.1007/s10817-008-9108-3}, + categories = {holocl}, + publisher = {Springer-Verlag}, + address = {Heidelberg}, + pdf = {http://www.brucker.ch/bibliography/download/2008/brucker.ea-extensible-2008-b.pdf}, + url = {http://www.brucker.ch/bibliography/abstract/brucker.ea-extensible-2008-b} + +} + +@Article{ brucker.ea:semantics:2009, + author = {Achim D. Brucker and Burkhart Wolff}, + title = {Semantics, Calculi, and Analysis for Object-oriented + Specifications}, + journal = {Acta Informatica}, + classification= {journal}, + areas = {formal methods, software}, + keywords = {UML, OCL, object-oriented specification, refinement, + formal methods}, + abstract = {We present a formal semantics for an object-oriented + specification language. The formal semantics is presented + as a conservative shallow embedding in Isabelle/HOL and the + language is oriented towards OCL formulae in the context of + UML class diagrams. On this basis, we formally derive + several equational and tableaux calculi, which form the + basis of an integrated proof environment including + automatic proof support and support for the analysis of + this type of specifications. + + We show applications of our proof environment to data + refinement based on an adapted standard refinement notion. + Thus, we provide an integrated formal method for + refinement-based object-oriented development.}, + year = {2009}, + language = {USenglish}, + public = {yes}, + issn = {0001-5903}, + doi = {10.1007/s00236-009-0093-8}, + categories = {holocl}, + pages = {255--284}, + month = jul, + volume = {46}, + number = {4}, + publisher = {Springer-Verlag}, + address = {Heidelberg}, + pdf = {http://www.brucker.ch/bibliography/download/2009/brucker.ea-semantics-2009.pdf}, + url = {http://www.brucker.ch/bibliography/abstract/brucker.ea-semantics-2009} + +} +@InCollection{ brucker.ea:ocl-null:2009, + author = {Achim D. Brucker and Matthias P. Krieger and Burkhart + Wolff}, + wsbooktitle = {The Pragmatics of OCL and Other Textual Specification + Languages}, + note = {Selected best papers from all satellite events of the + MoDELS 2009 conference.}, + booktitle = {Models in Software Engineering}, + publisher = {Springer-Verlag}, + address = {Heidelberg}, + series = {Lecture Notes in Computer Science}, + number = {6002}, + editor = {Sudipto Gosh}, + pages = {261--275}, + doi = {10.1007/978-3-642-12261-3_25}, + language = {USenglish}, + title = {Extending {OCL} with Null-References}, + year = {2009}, + classification= {workshop}, + categories = {holocl}, + location = {Denver, Colorado, USA}, + areas = {formal methods, software}, + public = {yes}, + abstract = {From its beginnings, OCL is based on a strict semantics + for undefinedness, with the exception of the logical + connectives of type Boolean that constitute a three-valued + propositional logic. Recent versions of the OCL standard + added a second exception element, which, similar to the + null references in object-oriented programming languages, + is given a non-strict semantics. Unfortunately, this + extension has been done in an ad hoc manner, which results + in several inconsistencies and contradictions. + + In this paper, we present a consistent formal semantics + (based on our HOL-OCL approach) that includes such a + non-strict exception element. We discuss the possible + consequences concerning class diagram semantics as well as + deduction rules. The benefits of our approach for the + specification-pragmatics of design level operation + contracts are demonstrated with a small case-study.}, + bibkey = {brucker.ea:ocl-null:2009}, + pdf = {http://www.brucker.ch/bibliography/download/2009/brucker.ea-ocl-null-2009.pdf}, + keywords = {HOL-OCL, UML, OCL, null reference, formal semantics}, + url = {http://www.brucker.ch/bibliography/abstract/brucker.ea-ocl-null-2009} + +} + +@InCollection{ brucker.ea:ocl-testing:2010, + abstract = {Automated test data generation is an important method for + the verification and validation of UML/OCL specifications. + In this paper, we present an extension of DNF-based test + case generation methods to cyclic class-diagrams and + recursive query operations on them. A key feature of our + approach is a implicit representation of object graphs + avoiding a representation based on object-id's; thus, our + approach avoids the generation of isomorphic object graphs + by using a concise and still human-readable symbolic + representation.}, + author = {Achim D. Brucker and Matthias P. Krieger and Delphine + Longuet and Burkhart Wolff}, + booktitle = {MoDELS Workshops}, + language = {USenglish}, + public = {yes}, + publisher = {Springer-Verlag}, + address = {Heidelberg}, + series = {Lecture Notes in Computer Science}, + number = {6627}, + classification= workshop, + areas = {formal methods, software}, + year = {2010}, + note = {Selected best papers from all satellite events of the + MoDELS 2010 conference. Workshop on OCL and Textual + Modelling.}, + categories = {holocl,holtestgen}, + keywords = {OCL, UML, test case generation, specification-based + testing}, + pages = {334--348}, + title = {A Specification-based Test Case Generation Method for + {UML}/{OCL}}, + editor = {J{\"u}rgen Dingel and Arnor Solberg}, + isbn = {978-3-642-21209-3}, + pdf = {http://www.brucker.ch/bibliography/download/2010/brucker.ea-ocl-testing-2010.pdf}, + doi = {10.1007/978-3-642-21210-9_33}, + url = {http://www.brucker.ch/bibliography/abstract/brucker.ea-ocl-testing-2010} + +} + + + +@InCollection{ brucker.ea:hol-testgen:2009, + abstract = {We present HOL-TestGen, an extensible test environment for + specification-based testing build upon the proof assistant + Isabelle. HOL-TestGen leverages the semi-automated + generation of test theorems (a form of a partition), and + their refinement to concrete test data, as well as the + automatic generation of a test driver for the execution and + test result verification. + + HOL-TestGen can also be understood as a unifying technical + and conceptual framework for presenting and investigating + the variety of unit and sequence test techniques in a + logically consistent way. }, + keywords = {symbolic test case generations, black box testing, white + box testing, theorem proving, interactive testing}, + location = {York, UK}, + author = {Achim D. Brucker and Burkhart Wolff}, + booktitle = {Fundamental Approaches to Software Engineering + {(FASE09)}}, + talk = {talk:brucker.ea:hol-testgen:2009}, + language = {USenglish}, + publisher = {Springer-Verlag}, + address = {Heidelberg}, + series = {Lecture Notes in Computer Science}, + number = {5503}, + doi = {10.1007/978-3-642-00593-0_28}, + pages = {417--420}, + editor = {Marsha Chechik and Martin Wirsing}, + title = {{HOL-TestGen}: An Interactive Test-case Generation + Framework}, + categories = {holtestgen}, + classification= {conference}, + areas = {formal methods, software}, + year = {2009}, + pdf = {http://www.brucker.ch/bibliography/download/2009/brucker.ea-hol-testgen-2009.pdf}, + public = {yes}, + url = {http://www.brucker.ch/bibliography/abstract/brucker.ea-hol-testgen-2009} + +} + +@inproceedings{DBLP:conf/models/BruckerLTW13, + author = {Achim D. Brucker and + Delphine Longuet and + Fr{\'e}d{\'e}ric Tuong and + Burkhart Wolff}, + title = {On the Semantics of Object-Oriented Data Structures and + Path Expressions}, + booktitle = {OCL@MoDELS}, + year = {2013}, + pages = {23-32}, + ee = {http://ceur-ws.org/Vol-1092/brucker.pdf}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + + +@InProceedings{ riazanov.ea:vampire:1999, + author = {Alexandre Riazanov and Andrei Voronkov}, + title = {Vampire}, + booktitle = {CADE}, + year = 1999, + pages = {292--296}, + doi = {10.1007/3-540-48660-7_26}, + crossref = {ganzinger:automated:1999} +} + +@Proceedings{ ganzinger:automated:1999, + editor = {Harald Ganzinger}, + title = {Automated Deduction - CADE-16, 16th International + Conference on Automated Deduction, Trento, Italy, July + 7-10, 1999, Proceedings}, + booktitle = {CADE}, + publisher = pub-springer, + series = s-lncs, + volume = 1632, + year = 1999, + isbn = {3-540-66222-7} +} +@Booklet{ levens.ea:jml:2007, + bibkey = {levens.ea:jml:2007}, + author = {Gary T. Leavens and Erik Poll and Curtis Clifton and + Yoonsik Cheon and Clyde Ruby and David R. Cok and Peter + M\"{u}ller and Joseph Kiniry and Patrice Chalin}, + title = {{\acs{jml}} Reference Manual (Revision 1.2)}, + month = feb, + year = 2007, + organization = {Department of Computer Science, Iowa State University.}, + note = {Available from \url{http://www.jmlspecs.org}}, + acknowledgement={brucker, 2007-04-23} +} + diff --git a/document/root.tex b/document/root.tex new file mode 100644 index 0000000..6c3b0b6 --- /dev/null +++ b/document/root.tex @@ -0,0 +1,157 @@ +\documentclass[11pt,a4paper,openright,twoside,abstracton]{scrreprt} +\usepackage{fixltx2e} +\usepackage{isabelle,isabellesym} +\usepackage[nocolortable, noaclist]{hol-ocl-isar} +\usepackage{booktabs} +\usepackage{graphicx} +\usepackage{amssymb} +\usepackage[numbers, sort&compress, sectionbib]{natbib} +\usepackage[caption=false]{subfig} +\usepackage{lstisar} +\usepackage{tabu} +\usepackage[]{mathtools} +\usepackage{prooftree} +\usepackage{aeguill} +\usepackage[pdfpagelabels, pageanchor=false, plainpages=false]{hyperref} +% \usepackage[draft]{fixme} + +% MathOCl expressions +\colorlet{MathOclColor}{Black} +\colorlet{HolOclColor}{Black} +\colorlet{OclColor}{Black} +% +\sloppy + +\uchyph=0 +\graphicspath{{data/},{figures/}} +\allowdisplaybreaks + +\renewcommand{\HolTrue}{\mathrm{true}} +\renewcommand{\HolFalse}{\mathrm{false}} +\newcommand{\ptmi}[1]{\using{\mi{#1}}} +\newcommand{\Lemma}[1]{{\color{BrickRed}% + \mathbf{\operatorname{lemma}}}~\text{#1:}\quad} +\newcommand{\done}{{\color{OliveGreen}\operatorname{done}}} +\newcommand{\apply}[1]{{\holoclthykeywordstyle% + \operatorname{apply}}(\text{#1})} +\newcommand{\fun} {{\holoclthykeywordstyle\operatorname{fun}}} +\newcommand{\definitionS} {{\holoclthykeywordstyle\operatorname{definition}}} +\newcommand{\where} {{\holoclthykeywordstyle\operatorname{where}}} +\newcommand{\datatype} {{\holoclthykeywordstyle\operatorname{datatype}}} +\newcommand{\types} {{\holoclthykeywordstyle\operatorname{types}}} +\newcommand{\pglabel}[1]{\text{#1}} +\renewcommand{\isasymOclUndefined}{\ensuremath{\mathtt{invalid}}} +\newcommand{\isasymOclNull}{\ensuremath{\mathtt{null}}} +\newcommand{\isasymOclInvalid}{\isasymOclUndefined} +\DeclareMathOperator{\inv}{inv} +\newcommand{\Null}[1]{{\ensuremath{\mathtt{null}_\text{{#1}}}}} +\newcommand{\testgen}{HOL-TestGen\xspace} +\newcommand{\HolOption}{\mathrm{option}} +\newcommand{\ran}{\mathrm{ran}} +\newcommand{\dom}{\mathrm{dom}} +\newcommand{\typedef}{\mathrm{typedef}} +\newcommand{\mi}[1]{\,\text{#1}} +\newcommand{\state}[1]{\ifthenelse{\equal{}{#1}}% + {\operatorname{state}}% + {\operatorname{\mathit{state}}(#1)}% +} +\newcommand{\mocl}[1]{\text{\inlineocl{#1}}} +\DeclareMathOperator{\TCnull}{null} +\DeclareMathOperator{\HolNull}{null} +\DeclareMathOperator{\HolBot}{bot} + + +% urls in roman style, theory text in math-similar italics +\urlstyle{rm} +\isabellestyle{it} +\newcommand{\ie}{i.\,e.\xspace} +\newcommand{\eg}{e.\,g.\xspace} +\renewcommand{\isamarkupheader}[1]{\chapter{#1}} +\renewcommand{\isamarkupsection}[1]{\section{#1}} +\renewcommand{\isamarkupsubsection}[1]{\subsection{#1}} +\renewcommand{\isamarkupsubsubsection}[1]{\subsubsection{#1}} +\renewcommand{\isamarkupsect}[1]{\section{#1}} +\renewcommand{\isamarkupsubsect}[1]{\susubsection{#1}} +\renewcommand{\isamarkupsubsubsect}[1]{\subsubsection{#1}} + +\begin{document} +\renewcommand{\subsubsectionautorefname}{Section} +\renewcommand{\subsectionautorefname}{Section} +\renewcommand{\sectionautorefname}{Section} +\renewcommand{\chapterautorefname}{Chapter} +\newcommand{\subtableautorefname}{\tableautorefname} +\newcommand{\subfigureautorefname}{\figureautorefname} + +\title{Featherweight OCL} +\subtitle{A Proposal for a Machine-Checked Formal Semantics for OCL 2.5} +\author{% + \href{http://www.brucker.ch/}{Achim D. Brucker}\footnotemark[1] + \and + \href{https://www.lri.fr/~tuong/}{Fr\'ed\'eric Tuong}\footnotemark[3] + \and + \href{https://www.lri.fr/~wolff/}{Burkhart Wolff}\footnotemark[2]} +\publishers{% + \footnotemark[1]~SAP AG, Vincenz-Priessnitz-Str. 1, 76131 Karlsruhe, + Germany \texorpdfstring{\\}{} \href{mailto:"Achim D. Brucker" + }{achim.brucker@sap.com}\\[2em] + % + \footnotemark[3]~Univ. Paris-Sud, IRT SystemX, 8 av.~de la Vauve, \\ + 91120 Palaiseau, France\\ + frederic.tuong@\{u-psud, irt-systemx\}.fr\\[2em] + % + \footnotemark[2]~Univ. Paris-Sud, Laboratoire LRI, UMR8623, 91405 Orsay, France\\ + CNRS, 91405 Orsay, France\texorpdfstring{\\}{} + \href{mailto:"Burkhart Wolff" }{burkhart.wolff@lri.fr} +} + + +\maketitle + +\begin{abstract} + The Unified Modeling Language (UML) is one of the few modeling + languages that is widely used in industry. While UML is mostly known + as diagrammatic modeling language (\eg, visualizing class models), + it is complemented by a textual language, called Object Constraint + Language (OCL). OCL is a textual annotation language, based on a + three-valued logic, that turns UML into a formal language. + Unfortunately the semantics of this specification language, captured + in the ``Annex A'' of the OCL standard, leads to different + interpretations of corner cases. Many of these corner cases had + been subject to formal analysis since more than ten years. + + The situation complicated when with version 2.3 the OCL was aligned + with the latest version of UML: this led to the extension of the + three-valued logic by a second exception element, called + \inlineocl{null}. While the first exception element + \inlineocl{invalid} has a strict semantics, \inlineocl{null} has a + non strict semantic interpretation. These semantic difficulties lead + to remarkable confusion for implementors of OCL compilers and + interpreters. + + In this paper, we provide a formalization of the core of OCL in + HOL\@. It provides denotational definitions, a logical calculus and + operational rules that allow for the execution of OCL expressions by + a mixture of term rewriting and code compilation. Our formalization + reveals several inconsistencies and contradictions in the current + version of the OCL standard. They reflect a challenge to define and + implement OCL tools in a uniform manner. Overall, this document is + intended to provide the basis for a machine-checked text ``Annex A'' + of the OCL standard targeting at tool implementors. + +\end{abstract} + +\tableofcontents +\include{introduction} +\include{formalization} +\include{conclusion} +\bibliographystyle{abbrvnat} +\bibliography{root} + +\end{document} + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: t +%%% End: + +% LocalWords: implementors denotational OCL UML diff --git a/examples/Employee_AnalysisModel_OCLPart.thy b/examples/Employee_AnalysisModel_OCLPart.thy new file mode 100644 index 0000000..9cd602d --- /dev/null +++ b/examples/Employee_AnalysisModel_OCLPart.thy @@ -0,0 +1,143 @@ +(***************************************************************************** + * Featherweight-OCL --- A Formal Semantics for UML-OCL Version OCL 2.4 + * for the OMG Standard. + * http://www.brucker.ch/projects/hol-testgen/ + * + * Employee_DesignModel_OCLPart.thy --- OCL Contracts and an Example. + * This file is part of HOL-TestGen. + * + * Copyright (c) 2012-2013 Université Paris-Sud, France + * 2013 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. + ******************************************************************************) + +header{* The Employee Analysis Model (OCL) *} + +theory + Employee_AnalysisModel_OCLPart +imports + Employee_AnalysisModel_UMLPart +begin +text {* \label{ex:employee-analysis:ocl} *} +section{* Standard State Infrastructure *} +text{* Ideally, these definitions are automatically generated from the class model. *} + +section{* Invariant *} +text{* These recursive predicates can be defined conservatively +by greatest fix-point +constructions---automatically. See~\cite{brucker.ea:hol-ocl-book:2006,brucker:interactive:2007} +for details. For the purpose of this example, we state them as axioms +here. *} +axiomatization inv_Person :: "Person \ Boolean" +where A : "(\ \ (\ self)) \ + (\ \ inv_Person(self)) = + ((\ \ (self .boss \ null)) \ + ( \ \ (self .boss <> null) \ (\ \ ((self .salary) `\ (self .boss .salary))) \ + (\ \ (inv_Person(self .boss))))) " + + +axiomatization inv_Person_at_pre :: "Person \ Boolean" +where B : "(\ \ (\ self)) \ + (\ \ inv_Person_at_pre(self)) = + ((\ \ (self .boss@pre \ null)) \ + ( \ \ (self .boss@pre <> null) \ + (\ \ (self .boss@pre .salary@pre `\ self .salary@pre)) \ + (\ \ (inv_Person_at_pre(self .boss@pre))))) " + +text{* A very first attempt to characterize the axiomatization by an inductive +definition - this can not be the last word since too weak (should be equality!) *} +coinductive inv :: "Person \ (\)st \ bool" where + "(\ \ (\ self)) \ ((\ \ (self .boss \ null)) \ + (\ \ (self .boss <> null) \ (\ \ (self .boss .salary `\ self .salary)) \ + ( (inv(self .boss))\ ))) + \ ( inv self \)" + +section{* The Contract of a Recursive Query *} +text{* The original specification of a recursive query : +\begin{ocl} +context Person::contents():Set(Integer) +post: result = if self.boss = null + then Set{i} + else self.boss.contents()->including(i) + endif +\end{ocl} *} + + +consts dot_contents :: "Person \ Set_Integer" ("(1(_).contents'('))" 50) + +axiomatization where dot_contents_def: +"(\ \ ((self).contents() \ result)) = + (if (\ self) \ = true \ + then ((\ \ true) \ + (\ \ (result \ if (self .boss \ null) + then (Set{self .salary}) + else (self .boss .contents()->including(self .salary)) + endif))) + else \ \ result \ invalid)" + + +consts dot_contents_AT_pre :: "Person \ Set_Integer" ("(1(_).contents@pre'('))" 50) + +axiomatization where dot_contents_AT_pre_def: +"(\ \ (self).contents@pre() \ result) = + (if (\ self) \ = true \ + then \ \ true \ (* pre *) + \ \ (result \ if (self).boss@pre \ null (* post *) + then Set{(self).salary@pre} + else (self).boss@pre .contents@pre()->including(self .salary@pre) + endif) + else \ \ result \ invalid)" + +text{* These \inlineocl{@pre} variants on methods are only available on queries, \ie, +operations without side-effect. *} + + +section{* The Contract of a Method *} +text{* +The specification in high-level OCL input syntax reads as follows: +\begin{ocl} +context Person::insert(x:Integer) +post: contents():Set(Integer) +contents() = contents@pre()->including(x) +\end{ocl} +*} + +consts dot_insert :: "Person \ Integer \ Void" ("(1(_).insert'(_'))" 50) + +axiomatization where dot_insert_def: +"(\ \ ((self).insert(x) \ result)) = + (if (\ self) \ = true \ \ (\ x) \ = true \ + then \ \ true \ + \ \ ((self).contents() \ (self).contents@pre()->including(x)) + else \ \ ((self).insert(x) \ invalid))" + +end diff --git a/examples/Employee_AnalysisModel_UMLPart.thy b/examples/Employee_AnalysisModel_UMLPart.thy new file mode 100644 index 0000000..0f8136b --- /dev/null +++ b/examples/Employee_AnalysisModel_UMLPart.thy @@ -0,0 +1,1341 @@ +(***************************************************************************** + * Featherweight-OCL --- A Formal Semantics for UML-OCL Version OCL 2.4 + * for the OMG Standard. + * http://www.brucker.ch/projects/hol-testgen/ + * + * Employee_DesignModel_UMLPart.thy --- OCL Contracts and an Example. + * This file is part of HOL-TestGen. + * + * Copyright (c) 2012-2013 Universite Paris-Sud, France + * 2013 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. + ******************************************************************************) + +header{* The Employee Analysis Model (UML) *} + +theory + Employee_AnalysisModel_UMLPart +imports + "../OCL_main" +begin + +text {* \label{ex:employee-analysis:uml} *} + +section{* Introduction *} +text{* + For certain concepts like classes and class-types, only a generic + definition for its resulting semantics can be given. Generic means, + there is a function outside HOL that ``compiles'' a concrete, + closed-world class diagram into a ``theory'' of this data model, + consisting of a bunch of definitions for classes, accessors, method, + casts, and tests for actual types, as well as proofs for the + fundamental properties of these operations in this concrete data + model. *} + +text{* Such generic function or ``compiler'' can be implemented in + Isabelle on the ML level. This has been done, for a semantics + following the open-world assumption, for UML 2.0 + in~\cite{brucker.ea:extensible:2008-b, brucker:interactive:2007}. In + this paper, we follow another approach for UML 2.4: we define the + concepts of the compilation informally, and present a concrete + example which is verified in Isabelle/HOL. *} + +subsection{* Outlining the Example *} + +text{* We are presenting here an ``analysis-model'' of the (slightly +modified) example Figure 7.3, page 20 of +the OCL standard~\cite{omg:ocl:2012}. +Here, analysis model means that associations +were really represented as relation on objects on the state---as is +intended by the standard---rather by pointers between objects as is +done in our ``design model'' (see \autoref{ex:employee-design:uml}). +To be precise, this theory contains the formalization of the data-part +covered by the UML class model (see \autoref{fig:person-ana}):*} + +text{* +\begin{figure} + \centering\scalebox{.3}{\includegraphics{figures/person.png}}% + \caption{A simple UML class model drawn from Figure 7.3, + page 20 of~\cite{omg:ocl:2012}. \label{fig:person-ana}} +\end{figure} +*} + +text{* This means that the association (attached to the association class +\inlineocl{EmployeeRanking}) with the association ends \inlineocl+boss+ and \inlineocl+employees+ is implemented +by the attribute \inlineocl+boss+ and the operation \inlineocl+employees+ (to be discussed in the OCL part +captured by the subsequent theory). +*} + +section{* Example Data-Universe and its Infrastructure *} +text{* Ideally, the following is generated automatically from a UML class model. *} + +(* @{text "'\"} -- \mathfrak{A} *) +text{* Our data universe consists in the concrete class diagram just of node's, +and implicitly of the class object. Each class implies the existence of a class +type defined for the corresponding object representations as follows: *} + +datatype type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n = mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid (* the oid to the person itself *) + "int option" (* the attribute "salary" or null *) + + +datatype type\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y = mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid (* the oid to the oclany itself *) + "(int option) option" + (* the extensions to "person"; used to denote + objects of actual type "person" casted to "oclany"; + in case of existence of several subclasses + of oclany, sums of extensions have to be provided. *) + +text{* Now, we construct a concrete ``universe of OclAny types'' by injection into a +sum type containing the class types. This type of OclAny will be used as instance +for all respective type-variables. *} + +datatype \ = in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n | in\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y type\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y + +text{* Having fixed the object universe, we can introduce type synonyms that exactly correspond +to OCL types. Again, we exploit that our representation of OCL is a ``shallow embedding'' with a +one-to-one correspondance of OCL-types to types of the meta-language HOL. *} +type_synonym Boolean = " \ Boolean" +type_synonym Integer = " \ Integer" +type_synonym Void = " \ Void" +type_synonym OclAny = "(\, type\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y option option) val" +type_synonym Person = "(\, type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n option option) val" +type_synonym Set_Integer = "(\, int option option) Set" +type_synonym Set_Person = "(\, type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n option option) Set" + +text{* Just a little check: *} +typ "Boolean" + +text{* To reuse key-elements of the library like referential equality, we have +to show that the object universe belongs to the type class ``oclany,'' \ie, + each class type has to provide a function @{term oid_of} yielding the object id (oid) of the object. *} +instantiation type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n :: object +begin + definition oid_of_type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_def: "oid_of x = (case x of mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid _ \ oid)" + instance .. +end + +instantiation type\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y :: object +begin + definition oid_of_type\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_def: "oid_of x = (case x of mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid _ \ oid)" + instance .. +end + +instantiation \ :: object +begin + definition oid_of_\_def: "oid_of x = (case x of + in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person \ oid_of person + | in\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oclany \ oid_of oclany)" + instance .. +end + + + + +section{* Instantiation of the Generic Strict Equality *} +text{* We instantiate the referential equality +on @{text "Person"} and @{text "OclAny"} *} + +defs(overloaded) StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n : "(x::Person) \ y \ StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t x y" +defs(overloaded) StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y : "(x::OclAny) \ y \ StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t x y" + +lemmas + cp_StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t[of "x::Person" "y::Person" "\", + simplified StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n[symmetric]] + cp_intro(9) [of "P::Person \Person""Q::Person \Person", + simplified StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n[symmetric] ] + StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def [of "x::Person" "y::Person", + simplified StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n[symmetric]] + StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_defargs [of _ "x::Person" "y::Person", + simplified StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n[symmetric]] + StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_strict1 + [of "x::Person", + simplified StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n[symmetric]] + StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_strict2 + [of "x::Person", + simplified StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n[symmetric]] + + + +text{* For each Class \emph{C}, we will have a casting operation \inlineocl{.oclAsType($C$)}, + a test on the actual type \inlineocl{.oclIsTypeOf($C$)} as well as its relaxed form + \inlineocl{.oclIsKindOf($C$)} (corresponding exactly to Java's \verb+instanceof+-operator. +*} +text{* Thus, since we have two class-types in our concrete class hierarchy, we have +two operations to declare and to provide two overloading definitions for the two static types. +*} + + +section{* OclAsType *} +subsection{* Definition *} + +consts OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y :: "'\ \ OclAny" ("(_) .oclAsType'(OclAny')") +consts OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n :: "'\ \ Person" ("(_) .oclAsType'(Person')") + +definition "OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_\ = (\u. \case u of in\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y a \ a + | in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n (mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid a) \ mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid \a\\)" + +lemma OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_\_some: "OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_\ x \ None" +by(simp add: OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_\_def) + +defs (overloaded) OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny: + "(X::OclAny) .oclAsType(OclAny) \ X" + +defs (overloaded) OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person: + "(X::Person) .oclAsType(OclAny) \ + (\\. case X \ of + \ \ invalid \ + | \\\ \ null \ + | \\mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid a \\ \ \\ (mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid \a\) \\)" + +definition "OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\ = (\u. case u of in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n p \ \p\ + | in\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y (mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid \a\) \ \mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid a\ + | _ \ None)" + +defs (overloaded) OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny: + "(X::OclAny) .oclAsType(Person) \ + (\\. case X \ of + \ \ invalid \ + | \\\ \ null \ + | \\mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid \ \\ \ invalid \ (* down-cast exception *) + | \\mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid \a\ \\ \ \\mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid a\\)" + +defs (overloaded) OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person: + "(X::Person) .oclAsType(Person) \ X " (* to avoid identity for null ? *) + + +lemmas [simp] = + OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny + OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person + +subsection{* Context Passing *} + +lemma cp_OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_Person: "cp P \ cp(\X. (P (X::Person)::Person) .oclAsType(OclAny))" +by(rule cpI1, simp_all add: OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person) +lemma cp_OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_OclAny: "cp P \ cp(\X. (P (X::OclAny)::OclAny) .oclAsType(OclAny))" +by(rule cpI1, simp_all add: OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny) +lemma cp_OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_Person: "cp P \ cp(\X. (P (X::Person)::Person) .oclAsType(Person))" +by(rule cpI1, simp_all add: OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person) +lemma cp_OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_OclAny: "cp P \ cp(\X. (P (X::OclAny)::OclAny) .oclAsType(Person))" +by(rule cpI1, simp_all add: OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny) + +lemma cp_OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_OclAny: "cp P \ cp(\X. (P (X::Person)::OclAny) .oclAsType(OclAny))" +by(rule cpI1, simp_all add: OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny) +lemma cp_OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_Person: "cp P \ cp(\X. (P (X::OclAny)::Person) .oclAsType(OclAny))" +by(rule cpI1, simp_all add: OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person) +lemma cp_OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_OclAny: "cp P \ cp(\X. (P (X::Person)::OclAny) .oclAsType(Person))" +by(rule cpI1, simp_all add: OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny) +lemma cp_OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_Person: "cp P \ cp(\X. (P (X::OclAny)::Person) .oclAsType(Person))" +by(rule cpI1, simp_all add: OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person) + +lemmas [simp] = + cp_OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_Person + cp_OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_OclAny + cp_OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_Person + cp_OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_OclAny + + cp_OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_OclAny + cp_OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_Person + cp_OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_OclAny + cp_OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_Person + +subsection{* Execution with Invalid or Null as Argument *} + +lemma OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_strict : "(invalid::OclAny) .oclAsType(OclAny) = invalid" +by(simp) + +lemma OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_nullstrict : "(null::OclAny) .oclAsType(OclAny) = null" +by(simp) + +lemma OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_strict[simp] : "(invalid::Person) .oclAsType(OclAny) = invalid" +by(rule ext, simp add: bot_option_def invalid_def + OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person) + +lemma OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_nullstrict[simp] : "(null::Person) .oclAsType(OclAny) = null" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def + OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person) + +lemma OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_strict[simp] : "(invalid::OclAny) .oclAsType(Person) = invalid" +by(rule ext, simp add: bot_option_def invalid_def + OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny) + +lemma OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_nullstrict[simp] : "(null::OclAny) .oclAsType(Person) = null" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def + OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny) + +lemma OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_strict : "(invalid::Person) .oclAsType(Person) = invalid" +by(simp) +lemma OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_nullstrict : "(null::Person) .oclAsType(Person) = null" +by(simp) + +section{* OclIsTypeOf *} +subsection{* Definition *} + +consts OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y :: "'\ \ Boolean" ("(_).oclIsTypeOf'(OclAny')") +consts OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n :: "'\ \ Boolean" ("(_).oclIsTypeOf'(Person')") + +defs (overloaded) OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny: + "(X::OclAny) .oclIsTypeOf(OclAny) \ + (\\. case X \ of + \ \ invalid \ + | \\\ \ true \ (* invalid ?? *) + | \\mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid \ \\ \ true \ + | \\mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid \_\ \\ \ false \)" + + +defs (overloaded) OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person: + "(X::Person) .oclIsTypeOf(OclAny) \ + (\\. case X \ of + \ \ invalid \ + | \\\ \ true \ (* invalid ?? *) + | \\ _ \\ \ false \)" (* must have actual type Person otherwise *) + +defs (overloaded) OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny: + "(X::OclAny) .oclIsTypeOf(Person) \ + (\\. case X \ of + \ \ invalid \ + | \\\ \ true \ + | \\mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid \ \\ \ false \ + | \\mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid \_\ \\ \ true \)" + +defs (overloaded) OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person: + "(X::Person) .oclIsTypeOf(Person) \ + (\\. case X \ of + \ \ invalid \ + | _ \ true \)" + +subsection{* Context Passing *} + +lemma cp_OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_Person: "cp P \ cp(\X.(P(X::Person)::Person).oclIsTypeOf(OclAny))" +by(rule cpI1, simp_all add: OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person) +lemma cp_OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_OclAny: "cp P \ cp(\X.(P(X::OclAny)::OclAny).oclIsTypeOf(OclAny))" +by(rule cpI1, simp_all add: OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny) +lemma cp_OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_Person: "cp P \ cp(\X.(P(X::Person)::Person).oclIsTypeOf(Person))" +by(rule cpI1, simp_all add: OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person) +lemma cp_OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_OclAny: "cp P \ cp(\X.(P(X::OclAny)::OclAny).oclIsTypeOf(Person))" +by(rule cpI1, simp_all add: OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny) + + +lemma cp_OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_OclAny: "cp P \ cp(\X.(P(X::Person)::OclAny).oclIsTypeOf(OclAny))" +by(rule cpI1, simp_all add: OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny) +lemma cp_OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_Person: "cp P \ cp(\X.(P(X::OclAny)::Person).oclIsTypeOf(OclAny))" +by(rule cpI1, simp_all add: OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person) +lemma cp_OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_OclAny: "cp P \ cp(\X.(P(X::Person)::OclAny).oclIsTypeOf(Person))" +by(rule cpI1, simp_all add: OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny) +lemma cp_OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_Person: "cp P \ cp(\X.(P(X::OclAny)::Person).oclIsTypeOf(Person))" +by(rule cpI1, simp_all add: OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person) + +lemmas [simp] = + cp_OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_Person + cp_OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_OclAny + cp_OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_Person + cp_OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_OclAny + + cp_OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_OclAny + cp_OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_Person + cp_OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_OclAny + cp_OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_Person + +subsection{* Execution with Invalid or Null as Argument *} + +lemma OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_strict1[simp]: + "(invalid::OclAny) .oclIsTypeOf(OclAny) = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def + OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny) +lemma OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_strict2[simp]: + "(null::OclAny) .oclIsTypeOf(OclAny) = true" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def + OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny) +lemma OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_strict1[simp]: + "(invalid::Person) .oclIsTypeOf(OclAny) = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def + OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person) +lemma OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_strict2[simp]: + "(null::Person) .oclIsTypeOf(OclAny) = true" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def + OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person) +lemma OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_strict1[simp]: + "(invalid::OclAny) .oclIsTypeOf(Person) = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def + OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny) +lemma OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_strict2[simp]: + "(null::OclAny) .oclIsTypeOf(Person) = true" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def + OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny) +lemma OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_strict1[simp]: + "(invalid::Person) .oclIsTypeOf(Person) = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def + OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person) +lemma OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_strict2[simp]: + "(null::Person) .oclIsTypeOf(Person) = true" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def + OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person) + +subsection{* Up Down Casting *} + +lemma actualType_larger_staticType: +assumes isdef: "\ \ (\ X)" +shows "\ \ (X::Person) .oclIsTypeOf(OclAny) \ false" +using isdef +by(auto simp : null_option_def bot_option_def + OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person foundation22 foundation16) + +lemma down_cast_type: +assumes isOclAny: "\ \ (X::OclAny) .oclIsTypeOf(OclAny)" +and non_null: "\ \ (\ X)" +shows "\ \ (X .oclAsType(Person)) \ invalid" +using isOclAny non_null +apply(auto simp : bot_fun_def null_fun_def null_option_def bot_option_def null_def invalid_def + OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny foundation22 foundation16 + split: option.split type\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y.split type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n.split) +by(simp add: OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny OclValid_def false_def true_def) + +lemma down_cast_type': +assumes isOclAny: "\ \ (X::OclAny) .oclIsTypeOf(OclAny)" +and non_null: "\ \ (\ X)" +shows "\ \ not (\ (X .oclAsType(Person)))" +by(rule foundation15[THEN iffD1], simp add: down_cast_type[OF assms]) + +lemma up_down_cast : +assumes isdef: "\ \ (\ X)" +shows "\ \ ((X::Person) .oclAsType(OclAny) .oclAsType(Person) \ X)" +using isdef +by(auto simp : null_fun_def null_option_def bot_option_def null_def invalid_def + OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny foundation22 foundation16 + split: option.split type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n.split) + + +lemma up_down_cast_Person_OclAny_Person [simp]: +shows "((X::Person) .oclAsType(OclAny) .oclAsType(Person) = X)" + apply(rule ext, rename_tac \) + apply(rule foundation22[THEN iffD1]) + apply(case_tac "\ \ (\ X)", simp add: up_down_cast) + apply(simp add: def_split_local, elim disjE) + apply(erule StrongEq_L_subst2_rev, simp, simp)+ +done + +lemma up_down_cast_Person_OclAny_Person': assumes "\ \ \ X" +shows "\ \ (((X :: Person) .oclAsType(OclAny) .oclAsType(Person)) \ X)" + apply(simp only: up_down_cast_Person_OclAny_Person StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n) +by(rule StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_sym, simp add: assms) + +lemma up_down_cast_Person_OclAny_Person'': assumes "\ \ \ (X :: Person)" +shows "\ \ (X .oclIsTypeOf(Person) implies (X .oclAsType(OclAny) .oclAsType(Person)) \ X)" + apply(simp add: OclValid_def) + apply(subst cp_OclImplies) + apply(simp add: StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_sym[OF assms, simplified OclValid_def]) + apply(subst cp_OclImplies[symmetric]) +by (simp add: OclImplies_true) + + +section{* OclIsKindOf *} +subsection{* Definition *} + +consts OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y :: "'\ \ Boolean" ("(_).oclIsKindOf'(OclAny')") +consts OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n :: "'\ \ Boolean" ("(_).oclIsKindOf'(Person')") + +defs (overloaded) OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny: + "(X::OclAny) .oclIsKindOf(OclAny) \ + (\\. case X \ of + \ \ invalid \ + | _ \ true \)" + +defs (overloaded) OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person: + "(X::Person) .oclIsKindOf(OclAny) \ + (\\. case X \ of + \ \ invalid \ + | _\ true \)" + +defs (overloaded) OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny: + "(X::OclAny) .oclIsKindOf(Person) \ + (\\. case X \ of + \ \ invalid \ + | \\\ \ true \ + | \\mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid \ \\ \ false \ + | \\mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid \_\ \\ \ true \)" + +defs (overloaded) OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person: + "(X::Person) .oclIsKindOf(Person) \ + (\\. case X \ of + \ \ invalid \ + | _ \ true \)" + +subsection{* Context Passing *} + +lemma cp_OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_Person: "cp P \ cp(\X.(P(X::Person)::Person).oclIsKindOf(OclAny))" +by(rule cpI1, simp_all add: OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person) +lemma cp_OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_OclAny: "cp P \ cp(\X.(P(X::OclAny)::OclAny).oclIsKindOf(OclAny))" +by(rule cpI1, simp_all add: OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny) +lemma cp_OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_Person: "cp P \ cp(\X.(P(X::Person)::Person).oclIsKindOf(Person))" +by(rule cpI1, simp_all add: OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person) +lemma cp_OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_OclAny: "cp P \ cp(\X.(P(X::OclAny)::OclAny).oclIsKindOf(Person))" +by(rule cpI1, simp_all add: OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny) + +lemma cp_OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_OclAny: "cp P \ cp(\X.(P(X::Person)::OclAny).oclIsKindOf(OclAny))" +by(rule cpI1, simp_all add: OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny) +lemma cp_OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_Person: "cp P \ cp(\X.(P(X::OclAny)::Person).oclIsKindOf(OclAny))" +by(rule cpI1, simp_all add: OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person) +lemma cp_OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_OclAny: "cp P \ cp(\X.(P(X::Person)::OclAny).oclIsKindOf(Person))" +by(rule cpI1, simp_all add: OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny) +lemma cp_OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_Person: "cp P \ cp(\X.(P(X::OclAny)::Person).oclIsKindOf(Person))" +by(rule cpI1, simp_all add: OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person) + +lemmas [simp] = + cp_OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_Person + cp_OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_OclAny + cp_OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_Person + cp_OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_OclAny + + cp_OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_OclAny + cp_OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_Person + cp_OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_OclAny + cp_OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_Person + +subsection{* Execution with Invalid or Null as Argument *} + +lemma OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_strict1[simp] : "(invalid::OclAny) .oclIsKindOf(OclAny) = invalid" +by(rule ext, simp add: invalid_def bot_option_def + OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny) + +lemma OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_strict2[simp] : "(null::OclAny) .oclIsKindOf(OclAny) = true" +by(rule ext, simp add: null_fun_def null_option_def + OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny) + +lemma OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_strict1[simp] : "(invalid::Person) .oclIsKindOf(OclAny) = invalid" +by(rule ext, simp add: bot_option_def invalid_def + OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person) + +lemma OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_strict2[simp] : "(null::Person) .oclIsKindOf(OclAny) = true" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def + OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person) + +lemma OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_strict1[simp]: "(invalid::OclAny) .oclIsKindOf(Person) = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def + OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny) + +lemma OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_strict2[simp]: "(null::OclAny) .oclIsKindOf(Person) = true" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def + OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny) + +lemma OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_strict1[simp]: "(invalid::Person) .oclIsKindOf(Person) = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def + OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person) + +lemma OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_strict2[simp]: "(null::Person) .oclIsKindOf(Person) = true" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def + OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person) + +subsection{* Up Down Casting *} + +lemma actualKind_larger_staticKind: +assumes isdef: "\ \ (\ X)" +shows "\ \ (X::Person) .oclIsKindOf(OclAny) \ true" +using isdef +by(auto simp : bot_option_def + OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person foundation22 foundation16) + +lemma down_cast_kind: +assumes isOclAny: "\ \ \ (X::OclAny) .oclIsKindOf(Person)" +and non_null: "\ \ (\ X)" +shows "\ \ (X .oclAsType(Person)) \ invalid" +using isOclAny non_null +apply(auto simp : bot_fun_def null_fun_def null_option_def bot_option_def null_def invalid_def + OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny foundation22 foundation16 + split: option.split type\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y.split type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n.split) +by(simp add: OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny OclValid_def false_def true_def) + +section{* OclAllInstances *} + +text{* To denote OCL-types occuring in OCL expressions syntactically---as, for example, as +``argument'' of \inlineisar{oclAllInstances()}---we use the inverses of the injection +functions into the object universes; we show that this is sufficient ``characterization.'' *} + +definition "Person \ OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\" +definition "OclAny \ OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_\" +lemmas [simp] = Person_def OclAny_def + +lemma OclAllInstances_generic\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_exec: "OclAllInstances_generic pre_post OclAny = + (\\. Abs_Set_0 \\ Some ` OclAny ` ran (heap (pre_post \)) \\)" +proof - + let ?S1 = "\\. OclAny ` ran (heap (pre_post \))" + let ?S2 = "\\. ?S1 \ - {None}" + have B : "\\. ?S2 \ \ ?S1 \" by auto + have C : "\\. ?S1 \ \ ?S2 \" by(auto simp: OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_\_some) + + show ?thesis by(insert equalityI[OF B C], simp) +qed + +lemma OclAllInstances_at_post\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_exec: "OclAny .allInstances() = + (\\. Abs_Set_0 \\ Some ` OclAny ` ran (heap (snd \)) \\)" +unfolding OclAllInstances_at_post_def +by(rule OclAllInstances_generic\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_exec) + +lemma OclAllInstances_at_pre\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_exec: "OclAny .allInstances@pre() = + (\\. Abs_Set_0 \\ Some ` OclAny ` ran (heap (fst \)) \\) " +unfolding OclAllInstances_at_pre_def +by(rule OclAllInstances_generic\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_exec) + +subsection{* OclIsTypeOf *} + +lemma OclAny_allInstances_generic_oclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y1: +assumes [simp]: "\x. pre_post (x, x) = x" +shows "\\. (\ \ ((OclAllInstances_generic pre_post OclAny)->forAll(X|X .oclIsTypeOf(OclAny))))" + apply(rule_tac x = \\<^sub>0 in exI, simp add: \\<^sub>0_def OclValid_def del: OclAllInstances_generic_def) + apply(simp only: assms OclForall_def refl if_True + OclAllInstances_generic_defined[simplified OclValid_def]) + apply(simp only: OclAllInstances_generic_def) + apply(subst (1 2 3) Abs_Set_0_inverse, simp add: bot_option_def) +by(simp add: OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny) + +lemma OclAny_allInstances_at_post_oclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y1: +"\\. (\ \ (OclAny .allInstances()->forAll(X|X .oclIsTypeOf(OclAny))))" +unfolding OclAllInstances_at_post_def +by(rule OclAny_allInstances_generic_oclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y1, simp) + +lemma OclAny_allInstances_at_pre_oclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y1: +"\\. (\ \ (OclAny .allInstances@pre()->forAll(X|X .oclIsTypeOf(OclAny))))" +unfolding OclAllInstances_at_pre_def +by(rule OclAny_allInstances_generic_oclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y1, simp) + +lemma OclAny_allInstances_generic_oclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y2: +assumes [simp]: "\x. pre_post (x, x) = x" +shows "\\. (\ \ not ((OclAllInstances_generic pre_post OclAny)->forAll(X|X .oclIsTypeOf(OclAny))))" +proof - fix oid a let ?t0 = "\heap = empty(oid \ in\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y (mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid \a\)), + assocs\<^sub>2 = empty, assocs\<^sub>3 = empty\" show ?thesis + apply(rule_tac x = "(?t0, ?t0)" in exI, simp add: OclValid_def del: OclAllInstances_generic_def) + apply(simp only: OclForall_def refl if_True + OclAllInstances_generic_defined[simplified OclValid_def]) + apply(simp only: OclAllInstances_generic_def OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_\_def) + apply(subst (1 2 3) Abs_Set_0_inverse, simp add: bot_option_def) + by(simp add: OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny OclNot_def OclAny_def) +qed + +lemma OclAny_allInstances_at_post_oclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y2: +"\\. (\ \ not (OclAny .allInstances()->forAll(X|X .oclIsTypeOf(OclAny))))" +unfolding OclAllInstances_at_post_def +by(rule OclAny_allInstances_generic_oclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y2, simp) + +lemma OclAny_allInstances_at_pre_oclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y2: +"\\. (\ \ not (OclAny .allInstances@pre()->forAll(X|X .oclIsTypeOf(OclAny))))" +unfolding OclAllInstances_at_pre_def +by(rule OclAny_allInstances_generic_oclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y2, simp) + +lemma Person_allInstances_generic_oclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n: +"\ \ ((OclAllInstances_generic pre_post Person)->forAll(X|X .oclIsTypeOf(Person)))" + apply(simp add: OclValid_def del: OclAllInstances_generic_def) + apply(simp only: OclForall_def refl if_True + OclAllInstances_generic_defined[simplified OclValid_def]) + apply(simp only: OclAllInstances_generic_def) + apply(subst (1 2 3) Abs_Set_0_inverse, simp add: bot_option_def) +by(simp add: OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person) + +lemma Person_allInstances_at_post_oclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n: +"\ \ (Person .allInstances()->forAll(X|X .oclIsTypeOf(Person)))" +unfolding OclAllInstances_at_post_def +by(rule Person_allInstances_generic_oclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n) + +lemma Person_allInstances_at_pre_oclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n: +"\ \ (Person .allInstances@pre()->forAll(X|X .oclIsTypeOf(Person)))" +unfolding OclAllInstances_at_pre_def +by(rule Person_allInstances_generic_oclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n) + +subsection{* OclIsKindOf *} +lemma OclAny_allInstances_generic_oclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y: +"\ \ ((OclAllInstances_generic pre_post OclAny)->forAll(X|X .oclIsKindOf(OclAny)))" + apply(simp add: OclValid_def del: OclAllInstances_generic_def) + apply(simp only: OclForall_def refl if_True + OclAllInstances_generic_defined[simplified OclValid_def]) + apply(simp only: OclAllInstances_generic_def) + apply(subst (1 2 3) Abs_Set_0_inverse, simp add: bot_option_def) +by(simp add: OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny) + +lemma OclAny_allInstances_at_post_oclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y: +"\ \ (OclAny .allInstances()->forAll(X|X .oclIsKindOf(OclAny)))" +unfolding OclAllInstances_at_post_def +by(rule OclAny_allInstances_generic_oclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y) + +lemma OclAny_allInstances_at_pre_oclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y: +"\ \ (OclAny .allInstances@pre()->forAll(X|X .oclIsKindOf(OclAny)))" +unfolding OclAllInstances_at_pre_def +by(rule OclAny_allInstances_generic_oclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y) + +lemma Person_allInstances_generic_oclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y: +"\ \ ((OclAllInstances_generic pre_post Person)->forAll(X|X .oclIsKindOf(OclAny)))" + apply(simp add: OclValid_def del: OclAllInstances_generic_def) + apply(simp only: OclForall_def refl if_True + OclAllInstances_generic_defined[simplified OclValid_def]) + apply(simp only: OclAllInstances_generic_def) + apply(subst (1 2 3) Abs_Set_0_inverse, simp add: bot_option_def) +by(simp add: OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person) + +lemma Person_allInstances_at_post_oclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y: +"\ \ (Person .allInstances()->forAll(X|X .oclIsKindOf(OclAny)))" +unfolding OclAllInstances_at_post_def +by(rule Person_allInstances_generic_oclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y) + +lemma Person_allInstances_at_pre_oclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y: +"\ \ (Person .allInstances@pre()->forAll(X|X .oclIsKindOf(OclAny)))" +unfolding OclAllInstances_at_pre_def +by(rule Person_allInstances_generic_oclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y) + +lemma Person_allInstances_generic_oclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n: +"\ \ ((OclAllInstances_generic pre_post Person)->forAll(X|X .oclIsKindOf(Person)))" + apply(simp add: OclValid_def del: OclAllInstances_generic_def) + apply(simp only: OclForall_def refl if_True + OclAllInstances_generic_defined[simplified OclValid_def]) + apply(simp only: OclAllInstances_generic_def) + apply(subst (1 2 3) Abs_Set_0_inverse, simp add: bot_option_def) +by(simp add: OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person) + +lemma Person_allInstances_at_post_oclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n: +"\ \ (Person .allInstances()->forAll(X|X .oclIsKindOf(Person)))" +unfolding OclAllInstances_at_post_def +by(rule Person_allInstances_generic_oclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n) + +lemma Person_allInstances_at_pre_oclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n: +"\ \ (Person .allInstances@pre()->forAll(X|X .oclIsKindOf(Person)))" +unfolding OclAllInstances_at_pre_def +by(rule Person_allInstances_generic_oclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n) + +section{* The Accessors (any, boss, salary) *} +text{*\label{sec:eam-accessors}*} +text{* Should be generated entirely from a class-diagram. *} + + +subsection{* Definition (of the association Employee-Boss) *} + +text{* We start with a oid for the association; this oid can be used +in presence of association classes to represent the association inside an object, +pretty much similar to the \inlineisar+Employee_DesignModel_UMLPart+, where we stored +an \verb+oid+ inside the class as ``pointer.'' *} + +definition oid\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\ ::"oid" where "oid\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\ = 10" + +text{* From there on, we can already define an empty state which must contain +for $\mathit{oid}_{Person}\mathcal{BOSS}$ the empty relation (encoded as association list, since there are +associations with a Sequence-like structure).*} + + +definition eval_extract :: "('\,('a::object) option option) val + \ (oid \ ('\,'c::null) val) + \ ('\,'c::null) val" +where "eval_extract X f = (\ \. case X \ of + \ \ invalid \ (* exception propagation *) + | \ \ \ \ invalid \ (* dereferencing null pointer *) + | \\ obj \\ \ f (oid_of obj) \)" +(* TODO: rephrasing as if-then-else and shifting to OCL_state. *) + +definition "choose\<^sub>2_1 = fst" +definition "choose\<^sub>2_2 = snd" +definition "choose\<^sub>3_1 = fst" +definition "choose\<^sub>3_2 = fst o snd" +definition "choose\<^sub>3_3 = snd o snd" + +definition "deref_assocs\<^sub>2" :: "('\ state \ '\ state \ '\ state) + \ (oid \ oid \ oid \ oid) + \ oid + \ (oid list \ oid \ ('\,'f)val) + \ oid + \ ('\, 'f::null)val" +where "deref_assocs\<^sub>2 pre_post to_from assoc_oid f oid = + (\\. case (assocs\<^sub>2 (pre_post \)) assoc_oid of + \ S \ \ f (map (choose\<^sub>2_2 \ to_from) + (filter (\ p. choose\<^sub>2_1(to_from p)=oid) S)) + oid \ + | _ \ invalid \)" + + +text{* The @{text pre_post}-parameter is configured with @{text fst} or +@{text snd}, the @{text to_from}-parameter either with the identity @{term id} or +the following combinator @{text switch}: *} +definition "switch\<^sub>2_1 = id" +definition "switch\<^sub>2_2 = (\(x,y). (y,x))" +definition "switch\<^sub>3_1 = id" +definition "switch\<^sub>3_2 = (\(x,y,z). (x,z,y))" +definition "switch\<^sub>3_3 = (\(x,y,z). (y,x,z))" +definition "switch\<^sub>3_4 = (\(x,y,z). (y,z,x))" +definition "switch\<^sub>3_5 = (\(x,y,z). (z,x,y))" +definition "switch\<^sub>3_6 = (\(x,y,z). (z,y,x))" + +definition select_object ::" (('\, 'b::null)val) + \ (('\,'b)val \ ('\,'c)val \ ('\, 'b)val) + \ (('\, 'b)val \ ('\, 'd)val) + \ (oid \ ('\,'c::null)val) + \ oid list + \ oid + \ ('\, 'd)val" +where "select_object mt incl smash deref l oid = smash(foldl incl mt (map deref l)) + (* smash returns null with mt in input (in this case, object contains null pointer) *)" + + +text{* The continuation @{text 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 OclIncluding OclANY f l oid )::('\, 'a::null)val" + +definition deref_oid\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n :: "(\ state \ \ state \ \ state) + \ (type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n \ (\, 'c::null)val) + \ oid + \ (\, 'c::null)val" +where "deref_oid\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n fst_snd f oid = (\\. case (heap (fst_snd \)) oid of + \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n obj \ \ f obj \ + | _ \ invalid \)" + + + +definition deref_oid\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y :: "(\ state \ \ state \ \ state) + \ (type\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y \ (\, 'c::null)val) + \ oid + \ (\, 'c::null)val" +where "deref_oid\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y fst_snd f oid = (\\. case (heap (fst_snd \)) oid of + \ in\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y obj \ \ f obj \ + | _ \ invalid \)" + +text{* pointer undefined in state or not referencing a type conform object representation *} + + +definition "select\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\ f = (\ X. case X of + (mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y _ \) \ null + | (mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y _ \any\) \ f (\x _. \\x\\) any)" + + +definition "select\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\ f = select_object mtSet OclIncluding OclANY (f (\x _. \\x\\))" + + +definition "select\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\ f = (\ X. case X of + (mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n _ \) \ null + | (mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n _ \salary\) \ f (\x _. \\x\\) salary)" + + +definition "deref_assocs\<^sub>2\\\\ fst_snd f = (\ mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid _ \ + deref_assocs\<^sub>2 fst_snd switch\<^sub>2_1 oid\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\ f oid)" + +definition "in_pre_state = fst" +definition "in_post_state = snd" + +definition "reconst_basetype = (\ convert x. convert x)" + +definition dot\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\ :: "OclAny \ _" ("(1(_).any)" 50) + where "(X).any = eval_extract X + (deref_oid\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y in_post_state + (select\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\ + reconst_basetype))" + +definition dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\ :: "Person \ Person" ("(1(_).boss)" 50) + where "(X).boss = eval_extract X + (deref_oid\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n in_post_state + (deref_assocs\<^sub>2\\\\ in_post_state + (select\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\ + (deref_oid\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n in_post_state))))" + +definition dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\ :: "Person \ Integer" ("(1(_).salary)" 50) + where "(X).salary = eval_extract X + (deref_oid\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n in_post_state + (select\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\ + reconst_basetype))" + +definition dot\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\_at_pre :: "OclAny \ _" ("(1(_).any@pre)" 50) + where "(X).any@pre = eval_extract X + (deref_oid\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y in_pre_state + (select\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\ + reconst_basetype))" + +definition dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\_at_pre:: "Person \ Person" ("(1(_).boss@pre)" 50) + where "(X).boss@pre = eval_extract X + (deref_oid\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n in_pre_state + (deref_assocs\<^sub>2\\\\ in_pre_state + (select\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\ + (deref_oid\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n in_pre_state))))" + +definition dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\_at_pre:: "Person \ Integer" ("(1(_).salary@pre)" 50) + where "(X).salary@pre = eval_extract X + (deref_oid\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n in_pre_state + (select\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\ + reconst_basetype))" + +lemmas [simp] = + dot\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\_def + dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\_def + dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\_def + dot\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\_at_pre_def + dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\_at_pre_def + dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\_at_pre_def + +subsection{* Context Passing *} + +lemmas [simp] = eval_extract_def + +lemma cp_dot\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\: "((X).any) \ = ((\_. X \).any) \" by simp +lemma cp_dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\: "((X).boss) \ = ((\_. X \).boss) \" by simp +lemma cp_dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\: "((X).salary) \ = ((\_. X \).salary) \" by simp + +lemma cp_dot\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\_at_pre: "((X).any@pre) \ = ((\_. X \).any@pre) \" by simp +lemma cp_dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\_at_pre: "((X).boss@pre) \ = ((\_. X \).boss@pre) \" by simp +lemma cp_dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\_at_pre: "((X).salary@pre) \ = ((\_. X \).salary@pre) \" by simp + +lemmas cp_dot\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\_I [simp, intro!]= + cp_dot\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\[THEN allI[THEN allI], + of "\ X _. X" "\ _ \. \", THEN cpI1] +lemmas cp_dot\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\_at_pre_I [simp, intro!]= + cp_dot\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\_at_pre[THEN allI[THEN allI], + of "\ X _. X" "\ _ \. \", THEN cpI1] + +lemmas cp_dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\_I [simp, intro!]= + cp_dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\[THEN allI[THEN allI], + of "\ X _. X" "\ _ \. \", THEN cpI1] +lemmas cp_dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\_at_pre_I [simp, intro!]= + cp_dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\_at_pre[THEN allI[THEN allI], + of "\ X _. X" "\ _ \. \", THEN cpI1] + +lemmas cp_dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\_I [simp, intro!]= + cp_dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\[THEN allI[THEN allI], + of "\ X _. X" "\ _ \. \", THEN cpI1] +lemmas cp_dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\_at_pre_I [simp, intro!]= + cp_dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\_at_pre[THEN allI[THEN allI], + of "\ X _. X" "\ _ \. \", THEN cpI1] + +subsection{* Execution with Invalid or Null as Argument *} + +lemma dot\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\_nullstrict [simp]: "(null).any = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def) +lemma dot\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\_at_pre_nullstrict [simp] : "(null).any@pre = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def) +lemma dot\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\_strict [simp] : "(invalid).any = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def) +lemma dot\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\_at_pre_strict [simp] : "(invalid).any@pre = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def) + + +lemma dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\_nullstrict [simp]: "(null).boss = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def) +lemma dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\_at_pre_nullstrict [simp] : "(null).boss@pre = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def) +lemma dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\_strict [simp] : "(invalid).boss = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def) +lemma dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\_at_pre_strict [simp] : "(invalid).boss@pre = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def) + + +lemma dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\_nullstrict [simp]: "(null).salary = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def) +lemma dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\_at_pre_nullstrict [simp] : "(null).salary@pre = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def) +lemma dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\_strict [simp] : "(invalid).salary = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def) +lemma dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\_at_pre_strict [simp] : "(invalid).salary@pre = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def) + + +section{* A Little Infra-structure on Example States *} + +text{* +The example we are defining in this section comes from the figure~\ref{fig:eam1_system-states}. +\begin{figure} +\includegraphics[width=\textwidth]{figures/pre-post.pdf} +\caption{(a) pre-state $\sigma_1$ and + (b) post-state $\sigma_1'$.} +\label{fig:eam1_system-states} +\end{figure} +*} + +definition OclInt1000 ("\\\\") where "OclInt1000 = (\ _ . \\1000\\)" +definition OclInt1200 ("\\\\") where "OclInt1200 = (\ _ . \\1200\\)" +definition OclInt1300 ("\\\\") where "OclInt1300 = (\ _ . \\1300\\)" +definition OclInt1800 ("\\\\") where "OclInt1800 = (\ _ . \\1800\\)" +definition OclInt2600 ("\\\\") where "OclInt2600 = (\ _ . \\2600\\)" +definition OclInt2900 ("\\\\") where "OclInt2900 = (\ _ . \\2900\\)" +definition OclInt3200 ("\\\\") where "OclInt3200 = (\ _ . \\3200\\)" +definition OclInt3500 ("\\\\") where "OclInt3500 = (\ _ . \\3500\\)" + +definition "oid0 \ 0" +definition "oid1 \ 1" +definition "oid2 \ 2" +definition "oid3 \ 3" +definition "oid4 \ 4" +definition "oid5 \ 5" +definition "oid6 \ 6" +definition "oid7 \ 7" +definition "oid8 \ 8" + +definition "person1 \ mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid0 \1300\" +definition "person2 \ mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid1 \1800\" +definition "person3 \ mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid2 None" +definition "person4 \ mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid3 \2900\" +definition "person5 \ mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid4 \3500\" +definition "person6 \ mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid5 \2500\" +definition "person7 \ mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid6 \\3200\\" +definition "person8 \ mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid7 None" +definition "person9 \ mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid8 \0\" + +definition + "\\<^sub>1 \ \ heap = empty(oid0 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n (mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid0 \1000\)) + (oid1 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n (mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid1 \1200\)) + (*oid2*) + (oid3 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n (mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid3 \2600\)) + (oid4 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person5) + (oid5 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n (mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid5 \2300\)) + (*oid6*) + (*oid7*) + (oid8 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person9), + assocs\<^sub>2 = empty(oid\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\ \ [(oid0,oid1),(oid3,oid4),(oid5,oid3)]), + assocs\<^sub>3 = empty \" + +definition + "\\<^sub>1' \ \ heap = empty(oid0 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person1) + (oid1 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person2) + (oid2 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person3) + (oid3 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person4) + (*oid4*) + (oid5 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person6) + (oid6 \ in\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y person7) + (oid7 \ in\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y person8) + (oid8 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person9), + assocs\<^sub>2 = empty(oid\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\ \ [(oid0,oid1),(oid1,oid1),(oid5,oid6),(oid6,oid6)]), + assocs\<^sub>3 = empty \" + +definition "\\<^sub>0 \ \ heap = empty, assocs\<^sub>2 = empty, assocs\<^sub>3 = empty \" + + +lemma basic_\_wff: "WFF(\\<^sub>1,\\<^sub>1')" +by(auto simp: WFF_def \\<^sub>1_def \\<^sub>1'_def + oid0_def oid1_def oid2_def oid3_def oid4_def oid5_def oid6_def oid7_def oid8_def + oid_of_\_def oid_of_type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_def oid_of_type\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_def + person1_def person2_def person3_def person4_def + person5_def person6_def person7_def person8_def person9_def) + +lemma [simp,code_unfold]: "dom (heap \\<^sub>1) = {oid0,oid1,(*,oid2*)oid3,oid4,oid5(*,oid6,oid7*),oid8}" +by(auto simp: \\<^sub>1_def) + +lemma [simp,code_unfold]: "dom (heap \\<^sub>1') = {oid0,oid1,oid2,oid3,(*,oid4*)oid5,oid6,oid7,oid8}" +by(auto simp: \\<^sub>1'_def) + +definition "X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 :: Person \ \ _ .\\ person1 \\" +definition "X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 :: Person \ \ _ .\\ person2 \\" +definition "X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3 :: Person \ \ _ .\\ person3 \\" +definition "X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4 :: Person \ \ _ .\\ person4 \\" +definition "X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5 :: Person \ \ _ .\\ person5 \\" +definition "X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6 :: Person \ \ _ .\\ person6 \\" +definition "X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7 :: OclAny \ \ _ .\\ person7 \\" +definition "X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8 :: OclAny \ \ _ .\\ person8 \\" +definition "X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9 :: Person \ \ _ .\\ person9 \\" + +lemma [code_unfold]: "((x::Person) \ y) = StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t x y" by(simp only: StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n) +lemma [code_unfold]: "((x::OclAny) \ y) = StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t x y" by(simp only: StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y) + +lemmas [simp,code_unfold] = + OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny + OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person + OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny + OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person + + OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny + OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person + OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny + OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person + + OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny + OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person + OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny + OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person + + +value "\s\<^sub>p\<^sub>r\<^sub>e . (s\<^sub>p\<^sub>r\<^sub>e,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .salary <> \\\\)" +value "\s\<^sub>p\<^sub>r\<^sub>e . (s\<^sub>p\<^sub>r\<^sub>e,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .salary \ \\\\)" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .salary@pre \ \\\\)" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .salary@pre <> \\\\)" +(*value "\s\<^sub>p\<^sub>r\<^sub>e . (s\<^sub>p\<^sub>r\<^sub>e,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .boss <> X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1)" +value "\s\<^sub>p\<^sub>r\<^sub>e . (s\<^sub>p\<^sub>r\<^sub>e,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .boss .salary \ \\\\)" +value "\s\<^sub>p\<^sub>r\<^sub>e . (s\<^sub>p\<^sub>r\<^sub>e,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .boss .boss <> X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1)" +value "\s\<^sub>p\<^sub>r\<^sub>e . (s\<^sub>p\<^sub>r\<^sub>e,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .boss .boss \ X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2)" +value " (\\<^sub>1,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .boss@pre .salary \ \\\\)" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .boss@pre .salary@pre \ \\\\)" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .boss@pre .salary@pre <> \\\\)" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .boss@pre \ X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2)" +value " (\\<^sub>1,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .boss@pre .boss \ X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2)" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .boss@pre .boss@pre \ null)" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ not(\(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .boss@pre .boss@pre .boss@pre))" +*) +lemma " (\\<^sub>1,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .oclIsMaintained())" +by(simp add: OclValid_def OclIsMaintained_def + \\<^sub>1_def \\<^sub>1'_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1_def person1_def + oid0_def oid1_def oid2_def oid3_def oid4_def oid5_def oid6_def + oid_of_option_def oid_of_type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_def) + +lemma "\s\<^sub>p\<^sub>r\<^sub>e s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (s\<^sub>p\<^sub>r\<^sub>e,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ ((X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .oclAsType(OclAny) .oclAsType(Person)) \ X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1)" +by(rule up_down_cast_Person_OclAny_Person', simp add: X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1_def) +value "\s\<^sub>p\<^sub>r\<^sub>e s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (s\<^sub>p\<^sub>r\<^sub>e,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .oclIsTypeOf(Person))" +value "\s\<^sub>p\<^sub>r\<^sub>e s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (s\<^sub>p\<^sub>r\<^sub>e,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ not(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .oclIsTypeOf(OclAny))" +value "\s\<^sub>p\<^sub>r\<^sub>e s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (s\<^sub>p\<^sub>r\<^sub>e,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .oclIsKindOf(Person))" +value "\s\<^sub>p\<^sub>r\<^sub>e s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (s\<^sub>p\<^sub>r\<^sub>e,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .oclIsKindOf(OclAny))" +value "\s\<^sub>p\<^sub>r\<^sub>e s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (s\<^sub>p\<^sub>r\<^sub>e,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ not(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .oclAsType(OclAny) .oclIsTypeOf(OclAny))" + + +value "\s\<^sub>p\<^sub>r\<^sub>e . (s\<^sub>p\<^sub>r\<^sub>e,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .salary \ \\\\)" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .salary@pre \ \\\\)" +(*value "\s\<^sub>p\<^sub>r\<^sub>e . (s\<^sub>p\<^sub>r\<^sub>e,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .boss \ X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2)" +value " (\\<^sub>1,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .boss .salary@pre \ \\\\)" +value " (\\<^sub>1,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .boss .boss@pre \ null)" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .boss@pre \ null)" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .boss@pre <> X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2)" +value " (\\<^sub>1,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .boss@pre <> (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .boss))" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ not(\(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .boss@pre .boss))" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ not(\(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .boss@pre .salary@pre))" +*)lemma " (\\<^sub>1,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .oclIsMaintained())" +by(simp add: OclValid_def OclIsMaintained_def + \\<^sub>1_def \\<^sub>1'_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2_def person2_def + oid0_def oid1_def oid2_def oid3_def oid4_def oid5_def oid6_def + oid_of_option_def oid_of_type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_def) + + +value "\s\<^sub>p\<^sub>r\<^sub>e . (s\<^sub>p\<^sub>r\<^sub>e,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3 .salary \ null)" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ not(\(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3 .salary@pre))" +(*value "\s\<^sub>p\<^sub>r\<^sub>e . (s\<^sub>p\<^sub>r\<^sub>e,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3 .boss \ null)" +value "\s\<^sub>p\<^sub>r\<^sub>e . (s\<^sub>p\<^sub>r\<^sub>e,\\<^sub>1') \ not(\(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3 .boss .salary))" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ not(\(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3 .boss@pre))" +*)lemma " (\\<^sub>1,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3 .oclIsNew())" +by(simp add: OclValid_def OclIsNew_def + \\<^sub>1_def \\<^sub>1'_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3_def person3_def + oid0_def oid1_def oid2_def oid3_def oid4_def oid5_def oid6_def oid8_def + oid_of_option_def oid_of_type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_def) + + +(*value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4 .boss@pre \ X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5)" +value " (\\<^sub>1,\\<^sub>1') \ not(\(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4 .boss@pre .salary))" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4 .boss@pre .salary@pre \ \\\\)" +*)lemma " (\\<^sub>1,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4 .oclIsMaintained())" +by(simp add: OclValid_def OclIsMaintained_def + \\<^sub>1_def \\<^sub>1'_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4_def person4_def + oid0_def oid1_def oid2_def oid3_def oid4_def oid5_def oid6_def + oid_of_option_def oid_of_type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_def) + + +value "\s\<^sub>p\<^sub>r\<^sub>e . (s\<^sub>p\<^sub>r\<^sub>e,\\<^sub>1') \ not(\(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5 .salary))" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5 .salary@pre \ \\\\)" +(*value "\s\<^sub>p\<^sub>r\<^sub>e . (s\<^sub>p\<^sub>r\<^sub>e,\\<^sub>1') \ not(\(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5 .boss))" +*)lemma " (\\<^sub>1,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5 .oclIsDeleted())" +by(simp add: OclNot_def OclValid_def OclIsDeleted_def + \\<^sub>1_def \\<^sub>1'_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5_def person5_def + oid0_def oid1_def oid2_def oid3_def oid4_def oid5_def oid6_def oid7_def oid8_def + oid_of_option_def oid_of_type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_def) + + +(* (* access to an oclany object not yet supported *) value " (\\<^sub>1,\\<^sub>1') \ ((X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6 .boss .salary) \ \\\\ )"*) +(*value "\s\<^sub>p\<^sub>r\<^sub>e . (s\<^sub>p\<^sub>r\<^sub>e,\\<^sub>1') \ not(\(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6 .boss .salary@pre))" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6 .boss@pre \ X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4)" +value " (\\<^sub>1,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6 .boss@pre .salary \ \\\\)" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6 .boss@pre .salary@pre \ \\\\)" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6 .boss@pre .boss@pre \ X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5)" +*)lemma " (\\<^sub>1,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6 .oclIsMaintained())" +by(simp add: OclValid_def OclIsMaintained_def + \\<^sub>1_def \\<^sub>1'_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6_def person6_def + oid0_def oid1_def oid2_def oid3_def oid4_def oid5_def oid6_def + oid_of_option_def oid_of_type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_def) + + +(* (* access to an oclany object not yet supported *) value " (\\<^sub>1,\\<^sub>1') \ ((X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7 .oclAsType(Person) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6 .boss)))" *) +(* (* access to an oclany object not yet supported *) value " (\\<^sub>1,\\<^sub>1') \ ((X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7 .oclAsType(Person) .boss) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7 .oclAsType(Person)) )" *) +(* (* access to an oclany object not yet supported *) value " (\\<^sub>1,\\<^sub>1') \ ((X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7 .oclAsType(Person) .boss .salary) \ \\\\ )" *) +value "\s\<^sub>p\<^sub>r\<^sub>e s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (s\<^sub>p\<^sub>r\<^sub>e,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ \(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7 .oclAsType(Person))" +(*value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ not(\(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7 .oclAsType(Person) .boss@pre))" +*)lemma "\s\<^sub>p\<^sub>r\<^sub>e s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (s\<^sub>p\<^sub>r\<^sub>e,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ ((X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7 .oclAsType(Person) .oclAsType(OclAny) + .oclAsType(Person)) + \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7 .oclAsType(Person)))" +by(rule up_down_cast_Person_OclAny_Person', simp add: X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7_def OclValid_def valid_def person7_def) +lemma " (\\<^sub>1,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7 .oclIsNew())" +by(simp add: OclValid_def OclIsNew_def + \\<^sub>1_def \\<^sub>1'_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7_def person7_def + oid0_def oid1_def oid2_def oid3_def oid4_def oid5_def oid6_def oid8_def + oid_of_option_def oid_of_type\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_def) + + +value "\s\<^sub>p\<^sub>r\<^sub>e s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (s\<^sub>p\<^sub>r\<^sub>e,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8 <> X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7)" +value "\s\<^sub>p\<^sub>r\<^sub>e s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (s\<^sub>p\<^sub>r\<^sub>e,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ not(\(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8 .oclAsType(Person)))" +value "\s\<^sub>p\<^sub>r\<^sub>e s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (s\<^sub>p\<^sub>r\<^sub>e,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8 .oclIsTypeOf(OclAny))" +value "\s\<^sub>p\<^sub>r\<^sub>e s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (s\<^sub>p\<^sub>r\<^sub>e,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ not(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8 .oclIsTypeOf(Person))" +value "\s\<^sub>p\<^sub>r\<^sub>e s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (s\<^sub>p\<^sub>r\<^sub>e,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ not(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8 .oclIsKindOf(Person))" +value "\s\<^sub>p\<^sub>r\<^sub>e s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (s\<^sub>p\<^sub>r\<^sub>e,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8 .oclIsKindOf(OclAny))" + + +lemma \_modifiedonly: "(\\<^sub>1,\\<^sub>1') \ (Set{ X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .oclAsType(OclAny) + , X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .oclAsType(OclAny) + (*, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3 .oclAsType(OclAny)*) + , X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4 .oclAsType(OclAny) + (*, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5 .oclAsType(OclAny)*) + , X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6 .oclAsType(OclAny) + (*, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7 .oclAsType(OclAny)*) + (*, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8 .oclAsType(OclAny)*) + (*, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9 .oclAsType(OclAny)*)}->oclIsModifiedOnly())" + apply(simp add: OclIsModifiedOnly_def OclValid_def + oid0_def oid1_def oid2_def oid3_def oid4_def oid5_def oid6_def oid7_def oid8_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9_def + person1_def person2_def person3_def person4_def + person5_def person6_def person7_def person8_def person9_def + image_def) + apply(simp add: OclIncluding_rep_set mtSet_rep_set null_option_def bot_option_def) + apply(simp add: oid_of_option_def oid_of_type\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_def, clarsimp) + apply(simp add: \\<^sub>1_def \\<^sub>1'_def + oid0_def oid1_def oid2_def oid3_def oid4_def oid5_def oid6_def oid7_def oid8_def) +done + +lemma "(\\<^sub>1,\\<^sub>1') \ ((X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9 @pre (\x. \OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\ x\)) \ X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9)" +by(simp add: OclSelf_at_pre_def \\<^sub>1_def oid_of_option_def oid_of_type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9_def person9_def oid8_def OclValid_def StrongEq_def OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\_def) + +lemma "(\\<^sub>1,\\<^sub>1') \ ((X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9 @post (\x. \OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\ x\)) \ X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9)" +by(simp add: OclSelf_at_post_def \\<^sub>1'_def oid_of_option_def oid_of_type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9_def person9_def oid8_def OclValid_def StrongEq_def OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\_def) + +lemma "(\\<^sub>1,\\<^sub>1') \ (((X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9 .oclAsType(OclAny)) @pre (\x. \OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_\ x\)) \ + ((X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9 .oclAsType(OclAny)) @post (\x. \OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_\ x\)))" +proof - + + have including4 : "\a b c d \. + Set{\\. \\a\\, \\. \\b\\, \\. \\c\\, \\. \\d\\} \ = Abs_Set_0 \\ {\\a\\, \\b\\, \\c\\, \\d\\} \\" + apply(subst abs_rep_simp'[symmetric], simp) + by(simp add: OclIncluding_rep_set mtSet_rep_set) + + have excluding1: "\S a b c d e \. + (\_. Abs_Set_0 \\ {\\a\\, \\b\\, \\c\\, \\d\\} \\)->excluding(\\. \\e\\) \ = + Abs_Set_0 \\ {\\a\\, \\b\\, \\c\\, \\d\\} - {\\e\\} \\" + apply(simp add: OclExcluding_def) + apply(simp add: defined_def OclValid_def false_def true_def + bot_fun_def bot_Set_0_def null_fun_def null_Set_0_def) + apply(rule conjI) + apply(rule impI, subst (asm) Abs_Set_0_inject) apply( simp add: bot_option_def)+ + apply(rule conjI) + apply(rule impI, subst (asm) Abs_Set_0_inject) apply( simp add: bot_option_def null_option_def)+ + apply(subst Abs_Set_0_inverse, simp add: bot_option_def, simp) + done + + show ?thesis + apply(rule framing[where X = "Set{ X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .oclAsType(OclAny) + , X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .oclAsType(OclAny) + (*, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3 .oclAsType(OclAny)*) + , X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4 .oclAsType(OclAny) + (*, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5 .oclAsType(OclAny)*) + , X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6 .oclAsType(OclAny) + (*, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7 .oclAsType(OclAny)*) + (*, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8 .oclAsType(OclAny)*) + (*, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9 .oclAsType(OclAny)*)}"]) + apply(cut_tac \_modifiedonly) + apply(simp only: OclValid_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9_def + person1_def person2_def person3_def person4_def + person5_def person6_def person7_def person8_def person9_def + OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person) + apply(subst cp_OclIsModifiedOnly, subst cp_OclExcluding, + subst (asm) cp_OclIsModifiedOnly, simp add: including4 excluding1) + + apply(simp only: X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9_def + person1_def person2_def person3_def person4_def + person5_def person6_def person7_def person8_def person9_def) + apply(simp add: OclIncluding_rep_set mtSet_rep_set + oid0_def oid1_def oid2_def oid3_def oid4_def oid5_def oid6_def oid7_def oid8_def) + apply(simp add: StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def oid_of_option_def oid_of_type\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_def OclNot_def OclValid_def + null_option_def bot_option_def) + done +qed + +lemma perm_\\<^sub>1' : "\\<^sub>1' = \ heap = empty + (oid8 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person9) + (oid7 \ in\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y person8) + (oid6 \ in\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y person7) + (oid5 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person6) + (*oid4*) + (oid3 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person4) + (oid2 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person3) + (oid1 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person2) + (oid0 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person1) + , assocs\<^sub>2 = assocs\<^sub>2 \\<^sub>1' + , assocs\<^sub>3 = assocs\<^sub>3 \\<^sub>1' \" +proof - + note P = fun_upd_twist + show ?thesis + apply(simp add: \\<^sub>1'_def + oid0_def oid1_def oid2_def oid3_def oid4_def oid5_def oid6_def oid7_def oid8_def) + apply(subst (1) P, simp) + apply(subst (2) P, simp) apply(subst (1) P, simp) + apply(subst (3) P, simp) apply(subst (2) P, simp) apply(subst (1) P, simp) + apply(subst (4) P, simp) apply(subst (3) P, simp) apply(subst (2) P, simp) apply(subst (1) P, simp) + apply(subst (5) P, simp) apply(subst (4) P, simp) apply(subst (3) P, simp) apply(subst (2) P, simp) apply(subst (1) P, simp) + apply(subst (6) P, simp) apply(subst (5) P, simp) apply(subst (4) P, simp) apply(subst (3) P, simp) apply(subst (2) P, simp) apply(subst (1) P, simp) + apply(subst (7) P, simp) apply(subst (6) P, simp) apply(subst (5) P, simp) apply(subst (4) P, simp) apply(subst (3) P, simp) apply(subst (2) P, simp) apply(subst (1) P, simp) + by(simp) +qed + +declare const_ss [simp] + +lemma "\\\<^sub>1. + (\\<^sub>1,\\<^sub>1') \ (Person .allInstances() \ Set{ X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4(*, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5*), X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6, + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7 .oclAsType(Person)(*, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8*), X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9 })" + apply(subst perm_\\<^sub>1') + apply(simp only: oid0_def oid1_def oid2_def oid3_def oid4_def oid5_def oid6_def oid7_def oid8_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9_def + person7_def) + apply(subst state_update_vs_allInstances_at_post_tc, simp, simp add: OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\_def, simp, rule const_StrictRefEq\<^sub>S\<^sub>e\<^sub>t_including, simp, simp, simp, rule OclIncluding_cong, simp, simp) + apply(subst state_update_vs_allInstances_at_post_tc, simp, simp add: OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\_def, simp, rule const_StrictRefEq\<^sub>S\<^sub>e\<^sub>t_including, simp, simp, simp, rule OclIncluding_cong, simp, simp) + apply(subst state_update_vs_allInstances_at_post_tc, simp, simp add: OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\_def, simp, rule const_StrictRefEq\<^sub>S\<^sub>e\<^sub>t_including, simp, simp, simp, rule OclIncluding_cong, simp, simp) + apply(subst state_update_vs_allInstances_at_post_tc, simp, simp add: OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\_def, simp, rule const_StrictRefEq\<^sub>S\<^sub>e\<^sub>t_including, simp, simp, simp, rule OclIncluding_cong, simp, simp) + apply(subst state_update_vs_allInstances_at_post_tc, simp, simp add: OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\_def, simp, rule const_StrictRefEq\<^sub>S\<^sub>e\<^sub>t_including, simp, simp, simp, rule OclIncluding_cong, simp, simp) + apply(subst state_update_vs_allInstances_at_post_tc, simp, simp add: OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\_def, simp, rule const_StrictRefEq\<^sub>S\<^sub>e\<^sub>t_including, simp, simp, simp, rule OclIncluding_cong, simp, simp) + apply(subst state_update_vs_allInstances_at_post_ntc, simp, simp add: OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\_def + person8_def, simp, rule const_StrictRefEq\<^sub>S\<^sub>e\<^sub>t_including, simp, simp, simp) + apply(subst state_update_vs_allInstances_at_post_tc, simp, simp add: OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\_def, simp, rule const_StrictRefEq\<^sub>S\<^sub>e\<^sub>t_including, simp, simp, simp, rule OclIncluding_cong, simp, simp) + apply(rule state_update_vs_allInstances_at_post_empty) +by(simp_all add: OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\_def) + +lemma "\\\<^sub>1. + (\\<^sub>1,\\<^sub>1') \ (OclAny .allInstances() \ Set{ X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .oclAsType(OclAny), X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .oclAsType(OclAny), + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3 .oclAsType(OclAny), X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4 .oclAsType(OclAny) + (*, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5*), X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6 .oclAsType(OclAny), + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9 .oclAsType(OclAny) })" + apply(subst perm_\\<^sub>1') + apply(simp only: oid0_def oid1_def oid2_def oid3_def oid4_def oid5_def oid6_def oid7_def oid8_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9_def + person1_def person2_def person3_def person4_def person5_def person6_def person9_def) + apply(subst state_update_vs_allInstances_at_post_tc, simp, simp add: OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_\_def, simp, rule const_StrictRefEq\<^sub>S\<^sub>e\<^sub>t_including, simp, simp, simp, rule OclIncluding_cong, simp, simp)+ + apply(rule state_update_vs_allInstances_at_post_empty) +by(simp_all add: OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_\_def) + +end diff --git a/examples/Employee_DesignModel_OCLPart.thy b/examples/Employee_DesignModel_OCLPart.thy new file mode 100644 index 0000000..96d37e4 --- /dev/null +++ b/examples/Employee_DesignModel_OCLPart.thy @@ -0,0 +1,143 @@ +(***************************************************************************** + * Featherweight-OCL --- A Formal Semantics for UML-OCL Version OCL 2.4 + * for the OMG Standard. + * http://www.brucker.ch/projects/hol-testgen/ + * + * Employee_DesignModel_OCLPart.thy --- OCL Contracts and an Example. + * This file is part of HOL-TestGen. + * + * Copyright (c) 2012-2013 Université Paris-Sud, France + * 2013 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. + ******************************************************************************) + +header{* The Employee Design Model (OCL) *} + +theory + Employee_DesignModel_OCLPart +imports + Employee_DesignModel_UMLPart +begin +text {* \label{ex:employee-design:ocl} *} +section{* Standard State Infrastructure *} +text{* Ideally, these definitions are automatically generated from the class model. *} + +section{* Invariant *} +text{* These recursive predicates can be defined conservatively +by greatest fix-point +constructions---automatically. See~\cite{brucker.ea:hol-ocl-book:2006,brucker:interactive:2007} +for details. For the purpose of this example, we state them as axioms +here. *} +axiomatization inv_Person :: "Person \ Boolean" +where A : "(\ \ (\ self)) \ + (\ \ inv_Person(self)) = + ((\ \ (self .boss \ null)) \ + ( \ \ (self .boss <> null) \ (\ \ ((self .salary) `\ (self .boss .salary))) \ + (\ \ (inv_Person(self .boss))))) " + + +axiomatization inv_Person_at_pre :: "Person \ Boolean" +where B : "(\ \ (\ self)) \ + (\ \ inv_Person_at_pre(self)) = + ((\ \ (self .boss@pre \ null)) \ + ( \ \ (self .boss@pre <> null) \ + (\ \ (self .boss@pre .salary@pre `\ self .salary@pre)) \ + (\ \ (inv_Person_at_pre(self .boss@pre))))) " + +text{* A very first attempt to characterize the axiomatization by an inductive +definition - this can not be the last word since too weak (should be equality!) *} +coinductive inv :: "Person \ (\)st \ bool" where + "(\ \ (\ self)) \ ((\ \ (self .boss \ null)) \ + (\ \ (self .boss <> null) \ (\ \ (self .boss .salary `\ self .salary)) \ + ( (inv(self .boss))\ ))) + \ ( inv self \)" + +section{* The Contract of a Recursive Query *} +text{* The original specification of a recursive query : +\begin{ocl} +context Person::contents():Set(Integer) +post: result = if self.boss = null + then Set{i} + else self.boss.contents()->including(i) + endif +\end{ocl} *} + + +consts dot_contents :: "Person \ Set_Integer" ("(1(_).contents'('))" 50) + +axiomatization where dot_contents_def: +"(\ \ ((self).contents() \ result)) = + (if (\ self) \ = true \ + then ((\ \ true) \ + (\ \ (result \ if (self .boss \ null) + then (Set{self .salary}) + else (self .boss .contents()->including(self .salary)) + endif))) + else \ \ result \ invalid)" + + +consts dot_contents_AT_pre :: "Person \ Set_Integer" ("(1(_).contents@pre'('))" 50) + +axiomatization where dot_contents_AT_pre_def: +"(\ \ (self).contents@pre() \ result) = + (if (\ self) \ = true \ + then \ \ true \ (* pre *) + \ \ (result \ if (self).boss@pre \ null (* post *) + then Set{(self).salary@pre} + else (self).boss@pre .contents@pre()->including(self .salary@pre) + endif) + else \ \ result \ invalid)" + +text{* These \inlineocl{@pre} variants on methods are only available on queries, \ie, +operations without side-effect. *} + + +section{* The Contract of a Method *} +text{* +The specification in high-level OCL input syntax reads as follows: +\begin{ocl} +context Person::insert(x:Integer) +post: contents():Set(Integer) +contents() = contents@pre()->including(x) +\end{ocl} +*} + +consts dot_insert :: "Person \ Integer \ Void" ("(1(_).insert'(_'))" 50) + +axiomatization where dot_insert_def: +"(\ \ ((self).insert(x) \ result)) = + (if (\ self) \ = true \ \ (\ x) \ = true \ + then \ \ true \ + \ \ ((self).contents() \ (self).contents@pre()->including(x)) + else \ \ ((self).insert(x) \ invalid))" + +end diff --git a/examples/Employee_DesignModel_UMLPart.thy b/examples/Employee_DesignModel_UMLPart.thy new file mode 100644 index 0000000..110b3d7 --- /dev/null +++ b/examples/Employee_DesignModel_UMLPart.thy @@ -0,0 +1,1273 @@ +(***************************************************************************** + * Featherweight-OCL --- A Formal Semantics for UML-OCL Version OCL 2.4 + * for the OMG Standard. + * http://www.brucker.ch/projects/hol-testgen/ + * + * Employee_DesignModel_UMLPart.thy --- OCL Contracts and an Example. + * This file is part of HOL-TestGen. + * + * Copyright (c) 2012-2013 Universite Paris-Sud, France + * 2013 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. + ******************************************************************************) + +header{* The Employee Design Model (UML) *} + +theory + Employee_DesignModel_UMLPart +imports + "../OCL_main" +begin + +text {* \label{ex:employee-design:uml} *} + +section{* Introduction *} +text{* + For certain concepts like classes and class-types, only a generic + definition for its resulting semantics can be given. Generic means, + there is a function outside HOL that ``compiles'' a concrete, + closed-world class diagram into a ``theory'' of this data model, + consisting of a bunch of definitions for classes, accessors, method, + casts, and tests for actual types, as well as proofs for the + fundamental properties of these operations in this concrete data + model. *} + +text{* Such generic function or ``compiler'' can be implemented in + Isabelle on the ML level. This has been done, for a semantics + following the open-world assumption, for UML 2.0 + in~\cite{brucker.ea:extensible:2008-b, brucker:interactive:2007}. In + this paper, we follow another approach for UML 2.4: we define the + concepts of the compilation informally, and present a concrete + example which is verified in Isabelle/HOL. *} + +subsection{* Outlining the Example *} + +text{* We are presenting here a ``design-model'' of the (slightly +modified) example Figure 7.3, page 20 of +the OCL standard~\cite{omg:ocl:2012}. To be precise, this theory contains the formalization of +the data-part covered by the UML class model (see \autoref{fig:person}):*} + +text{* +\begin{figure} + \centering\scalebox{.3}{\includegraphics{figures/person.png}}% + \caption{A simple UML class model drawn from Figure 7.3, + page 20 of~\cite{omg:ocl:2012}. \label{fig:person}} +\end{figure} +*} + +text{* This means that the association (attached to the association class +\inlineocl{EmployeeRanking}) with the association ends \inlineocl+boss+ and \inlineocl+employees+ is implemented +by the attribute \inlineocl+boss+ and the operation \inlineocl+employees+ (to be discussed in the OCL part +captured by the subsequent theory). +*} + +section{* Example Data-Universe and its Infrastructure *} +text{* Ideally, the following is generated automatically from a UML class model. *} + +(* @{text "'\"} -- \mathfrak{A} *) +text{* Our data universe consists in the concrete class diagram just of node's, +and implicitly of the class object. Each class implies the existence of a class +type defined for the corresponding object representations as follows: *} + +datatype type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n = mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid (* the oid to the person itself *) + "int option" (* the attribute "salary" or null *) + "oid option" (* the attribute "boss" or null *) + + +datatype type\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y = mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid (* the oid to the oclany itself *) + "(int option \ oid option) option" + (* the extensions to "person"; used to denote + objects of actual type "person" casted to "oclany"; + in case of existence of several subclasses + of oclany, sums of extensions have to be provided. *) + +text{* Now, we construct a concrete ``universe of OclAny types'' by injection into a +sum type containing the class types. This type of OclAny will be used as instance +for all respective type-variables. *} + +datatype \ = in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n | in\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y type\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y + +text{* Having fixed the object universe, we can introduce type synonyms that exactly correspond +to OCL types. Again, we exploit that our representation of OCL is a ``shallow embedding'' with a +one-to-one correspondance of OCL-types to types of the meta-language HOL. *} +type_synonym Boolean = " \ Boolean" +type_synonym Integer = " \ Integer" +type_synonym Void = " \ Void" +type_synonym OclAny = "(\, type\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y option option) val" +type_synonym Person = "(\, type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n option option) val" +type_synonym Set_Integer = "(\, int option option) Set" +type_synonym Set_Person = "(\, type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n option option) Set" + +text{* Just a little check: *} +typ "Boolean" + +text{* To reuse key-elements of the library like referential equality, we have +to show that the object universe belongs to the type class ``oclany,'' \ie, + each class type has to provide a function @{term oid_of} yielding the object id (oid) of the object. *} +instantiation type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n :: object +begin + definition oid_of_type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_def: "oid_of x = (case x of mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid _ _ \ oid)" + instance .. +end + +instantiation type\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y :: object +begin + definition oid_of_type\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_def: "oid_of x = (case x of mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid _ \ oid)" + instance .. +end + +instantiation \ :: object +begin + definition oid_of_\_def: "oid_of x = (case x of + in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person \ oid_of person + | in\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oclany \ oid_of oclany)" + instance .. +end + + + + +section{* Instantiation of the Generic Strict Equality *} +text{* We instantiate the referential equality +on @{text "Person"} and @{text "OclAny"} *} + +defs(overloaded) StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n : "(x::Person) \ y \ StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t x y" +defs(overloaded) StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y : "(x::OclAny) \ y \ StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t x y" + +lemmas + cp_StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t[of "x::Person" "y::Person" "\", + simplified StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n[symmetric]] + cp_intro(9) [of "P::Person \Person""Q::Person \Person", + simplified StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n[symmetric] ] + StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def [of "x::Person" "y::Person", + simplified StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n[symmetric]] + StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_defargs [of _ "x::Person" "y::Person", + simplified StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n[symmetric]] + StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_strict1 + [of "x::Person", + simplified StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n[symmetric]] + StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_strict2 + [of "x::Person", + simplified StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n[symmetric]] + + + +text{* For each Class \emph{C}, we will have a casting operation \inlineocl{.oclAsType($C$)}, + a test on the actual type \inlineocl{.oclIsTypeOf($C$)} as well as its relaxed form + \inlineocl{.oclIsKindOf($C$)} (corresponding exactly to Java's \verb+instanceof+-operator. +*} +text{* Thus, since we have two class-types in our concrete class hierarchy, we have +two operations to declare and to provide two overloading definitions for the two static types. +*} + + +section{* OclAsType *} +subsection{* Definition *} + +consts OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y :: "'\ \ OclAny" ("(_) .oclAsType'(OclAny')") +consts OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n :: "'\ \ Person" ("(_) .oclAsType'(Person')") + +definition "OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_\ = (\u. \case u of in\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y a \ a + | in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n (mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid a b) \ mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid \(a,b)\\)" + +lemma OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_\_some: "OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_\ x \ None" +by(simp add: OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_\_def) + +defs (overloaded) OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny: + "(X::OclAny) .oclAsType(OclAny) \ X" + +defs (overloaded) OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person: + "(X::Person) .oclAsType(OclAny) \ + (\\. case X \ of + \ \ invalid \ + | \\\ \ null \ + | \\mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid a b \\ \ \\ (mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid \(a,b)\) \\)" + +definition "OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\ = (\u. case u of in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n p \ \p\ + | in\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y (mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid \(a,b)\) \ \mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid a b\ + | _ \ None)" + +defs (overloaded) OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny: + "(X::OclAny) .oclAsType(Person) \ + (\\. case X \ of + \ \ invalid \ + | \\\ \ null \ + | \\mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid \ \\ \ invalid \ (* down-cast exception *) + | \\mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid \(a,b)\ \\ \ \\mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid a b \\)" + +defs (overloaded) OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person: + "(X::Person) .oclAsType(Person) \ X " (* to avoid identity for null ? *) + + +lemmas [simp] = + OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny + OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person + +subsection{* Context Passing *} + +lemma cp_OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_Person: "cp P \ cp(\X. (P (X::Person)::Person) .oclAsType(OclAny))" +by(rule cpI1, simp_all add: OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person) +lemma cp_OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_OclAny: "cp P \ cp(\X. (P (X::OclAny)::OclAny) .oclAsType(OclAny))" +by(rule cpI1, simp_all add: OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny) +lemma cp_OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_Person: "cp P \ cp(\X. (P (X::Person)::Person) .oclAsType(Person))" +by(rule cpI1, simp_all add: OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person) +lemma cp_OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_OclAny: "cp P \ cp(\X. (P (X::OclAny)::OclAny) .oclAsType(Person))" +by(rule cpI1, simp_all add: OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny) + +lemma cp_OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_OclAny: "cp P \ cp(\X. (P (X::Person)::OclAny) .oclAsType(OclAny))" +by(rule cpI1, simp_all add: OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny) +lemma cp_OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_Person: "cp P \ cp(\X. (P (X::OclAny)::Person) .oclAsType(OclAny))" +by(rule cpI1, simp_all add: OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person) +lemma cp_OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_OclAny: "cp P \ cp(\X. (P (X::Person)::OclAny) .oclAsType(Person))" +by(rule cpI1, simp_all add: OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny) +lemma cp_OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_Person: "cp P \ cp(\X. (P (X::OclAny)::Person) .oclAsType(Person))" +by(rule cpI1, simp_all add: OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person) + +lemmas [simp] = + cp_OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_Person + cp_OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_OclAny + cp_OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_Person + cp_OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_OclAny + + cp_OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_OclAny + cp_OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_Person + cp_OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_OclAny + cp_OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_Person + +subsection{* Execution with Invalid or Null as Argument *} + +lemma OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_strict : "(invalid::OclAny) .oclAsType(OclAny) = invalid" +by(simp) + +lemma OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_nullstrict : "(null::OclAny) .oclAsType(OclAny) = null" +by(simp) + +lemma OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_strict[simp] : "(invalid::Person) .oclAsType(OclAny) = invalid" +by(rule ext, simp add: bot_option_def invalid_def + OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person) + +lemma OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_nullstrict[simp] : "(null::Person) .oclAsType(OclAny) = null" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def + OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person) + +lemma OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_strict[simp] : "(invalid::OclAny) .oclAsType(Person) = invalid" +by(rule ext, simp add: bot_option_def invalid_def + OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny) + +lemma OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_nullstrict[simp] : "(null::OclAny) .oclAsType(Person) = null" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def + OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny) + +lemma OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_strict : "(invalid::Person) .oclAsType(Person) = invalid" +by(simp) +lemma OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_nullstrict : "(null::Person) .oclAsType(Person) = null" +by(simp) + +section{* OclIsTypeOf *} +subsection{* Definition *} + +consts OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y :: "'\ \ Boolean" ("(_).oclIsTypeOf'(OclAny')") +consts OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n :: "'\ \ Boolean" ("(_).oclIsTypeOf'(Person')") + +defs (overloaded) OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny: + "(X::OclAny) .oclIsTypeOf(OclAny) \ + (\\. case X \ of + \ \ invalid \ + | \\\ \ true \ (* invalid ?? *) + | \\mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid \ \\ \ true \ + | \\mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid \_\ \\ \ false \)" + + +defs (overloaded) OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person: + "(X::Person) .oclIsTypeOf(OclAny) \ + (\\. case X \ of + \ \ invalid \ + | \\\ \ true \ (* invalid ?? *) + | \\ _ \\ \ false \)" (* must have actual type Person otherwise *) + +defs (overloaded) OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny: + "(X::OclAny) .oclIsTypeOf(Person) \ + (\\. case X \ of + \ \ invalid \ + | \\\ \ true \ + | \\mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid \ \\ \ false \ + | \\mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid \_\ \\ \ true \)" + +defs (overloaded) OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person: + "(X::Person) .oclIsTypeOf(Person) \ + (\\. case X \ of + \ \ invalid \ + | _ \ true \)" + +subsection{* Context Passing *} + +lemma cp_OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_Person: "cp P \ cp(\X.(P(X::Person)::Person).oclIsTypeOf(OclAny))" +by(rule cpI1, simp_all add: OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person) +lemma cp_OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_OclAny: "cp P \ cp(\X.(P(X::OclAny)::OclAny).oclIsTypeOf(OclAny))" +by(rule cpI1, simp_all add: OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny) +lemma cp_OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_Person: "cp P \ cp(\X.(P(X::Person)::Person).oclIsTypeOf(Person))" +by(rule cpI1, simp_all add: OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person) +lemma cp_OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_OclAny: "cp P \ cp(\X.(P(X::OclAny)::OclAny).oclIsTypeOf(Person))" +by(rule cpI1, simp_all add: OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny) + + +lemma cp_OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_OclAny: "cp P \ cp(\X.(P(X::Person)::OclAny).oclIsTypeOf(OclAny))" +by(rule cpI1, simp_all add: OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny) +lemma cp_OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_Person: "cp P \ cp(\X.(P(X::OclAny)::Person).oclIsTypeOf(OclAny))" +by(rule cpI1, simp_all add: OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person) +lemma cp_OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_OclAny: "cp P \ cp(\X.(P(X::Person)::OclAny).oclIsTypeOf(Person))" +by(rule cpI1, simp_all add: OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny) +lemma cp_OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_Person: "cp P \ cp(\X.(P(X::OclAny)::Person).oclIsTypeOf(Person))" +by(rule cpI1, simp_all add: OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person) + +lemmas [simp] = + cp_OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_Person + cp_OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_OclAny + cp_OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_Person + cp_OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_OclAny + + cp_OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_OclAny + cp_OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_Person + cp_OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_OclAny + cp_OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_Person + +subsection{* Execution with Invalid or Null as Argument *} + +lemma OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_strict1[simp]: + "(invalid::OclAny) .oclIsTypeOf(OclAny) = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def + OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny) +lemma OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_strict2[simp]: + "(null::OclAny) .oclIsTypeOf(OclAny) = true" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def + OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny) +lemma OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_strict1[simp]: + "(invalid::Person) .oclIsTypeOf(OclAny) = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def + OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person) +lemma OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_strict2[simp]: + "(null::Person) .oclIsTypeOf(OclAny) = true" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def + OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person) +lemma OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_strict1[simp]: + "(invalid::OclAny) .oclIsTypeOf(Person) = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def + OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny) +lemma OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_strict2[simp]: + "(null::OclAny) .oclIsTypeOf(Person) = true" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def + OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny) +lemma OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_strict1[simp]: + "(invalid::Person) .oclIsTypeOf(Person) = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def + OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person) +lemma OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_strict2[simp]: + "(null::Person) .oclIsTypeOf(Person) = true" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def + OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person) + +subsection{* Up Down Casting *} + +lemma actualType_larger_staticType: +assumes isdef: "\ \ (\ X)" +shows "\ \ (X::Person) .oclIsTypeOf(OclAny) \ false" +using isdef +by(auto simp : null_option_def bot_option_def + OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person foundation22 foundation16) + +lemma down_cast_type: +assumes isOclAny: "\ \ (X::OclAny) .oclIsTypeOf(OclAny)" +and non_null: "\ \ (\ X)" +shows "\ \ (X .oclAsType(Person)) \ invalid" +using isOclAny non_null +apply(auto simp : bot_fun_def null_fun_def null_option_def bot_option_def null_def invalid_def + OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny foundation22 foundation16 + split: option.split type\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y.split type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n.split) +by(simp add: OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny OclValid_def false_def true_def) + +lemma down_cast_type': +assumes isOclAny: "\ \ (X::OclAny) .oclIsTypeOf(OclAny)" +and non_null: "\ \ (\ X)" +shows "\ \ not (\ (X .oclAsType(Person)))" +by(rule foundation15[THEN iffD1], simp add: down_cast_type[OF assms]) + +lemma up_down_cast : +assumes isdef: "\ \ (\ X)" +shows "\ \ ((X::Person) .oclAsType(OclAny) .oclAsType(Person) \ X)" +using isdef +by(auto simp : null_fun_def null_option_def bot_option_def null_def invalid_def + OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny foundation22 foundation16 + split: option.split type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n.split) + + +lemma up_down_cast_Person_OclAny_Person [simp]: +shows "((X::Person) .oclAsType(OclAny) .oclAsType(Person) = X)" + apply(rule ext, rename_tac \) + apply(rule foundation22[THEN iffD1]) + apply(case_tac "\ \ (\ X)", simp add: up_down_cast) + apply(simp add: def_split_local, elim disjE) + apply(erule StrongEq_L_subst2_rev, simp, simp)+ +done + +lemma up_down_cast_Person_OclAny_Person': assumes "\ \ \ X" +shows "\ \ (((X :: Person) .oclAsType(OclAny) .oclAsType(Person)) \ X)" + apply(simp only: up_down_cast_Person_OclAny_Person StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n) +by(rule StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_sym, simp add: assms) + +lemma up_down_cast_Person_OclAny_Person'': assumes "\ \ \ (X :: Person)" +shows "\ \ (X .oclIsTypeOf(Person) implies (X .oclAsType(OclAny) .oclAsType(Person)) \ X)" + apply(simp add: OclValid_def) + apply(subst cp_OclImplies) + apply(simp add: StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_sym[OF assms, simplified OclValid_def]) + apply(subst cp_OclImplies[symmetric]) +by (simp add: OclImplies_true) + + +section{* OclIsKindOf *} +subsection{* Definition *} + +consts OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y :: "'\ \ Boolean" ("(_).oclIsKindOf'(OclAny')") +consts OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n :: "'\ \ Boolean" ("(_).oclIsKindOf'(Person')") + +defs (overloaded) OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny: + "(X::OclAny) .oclIsKindOf(OclAny) \ + (\\. case X \ of + \ \ invalid \ + | _ \ true \)" + +defs (overloaded) OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person: + "(X::Person) .oclIsKindOf(OclAny) \ + (\\. case X \ of + \ \ invalid \ + | _\ true \)" + +defs (overloaded) OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny: + "(X::OclAny) .oclIsKindOf(Person) \ + (\\. case X \ of + \ \ invalid \ + | \\\ \ true \ + | \\mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid \ \\ \ false \ + | \\mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid \_\ \\ \ true \)" + +defs (overloaded) OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person: + "(X::Person) .oclIsKindOf(Person) \ + (\\. case X \ of + \ \ invalid \ + | _ \ true \)" + +subsection{* Context Passing *} + +lemma cp_OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_Person: "cp P \ cp(\X.(P(X::Person)::Person).oclIsKindOf(OclAny))" +by(rule cpI1, simp_all add: OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person) +lemma cp_OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_OclAny: "cp P \ cp(\X.(P(X::OclAny)::OclAny).oclIsKindOf(OclAny))" +by(rule cpI1, simp_all add: OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny) +lemma cp_OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_Person: "cp P \ cp(\X.(P(X::Person)::Person).oclIsKindOf(Person))" +by(rule cpI1, simp_all add: OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person) +lemma cp_OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_OclAny: "cp P \ cp(\X.(P(X::OclAny)::OclAny).oclIsKindOf(Person))" +by(rule cpI1, simp_all add: OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny) + +lemma cp_OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_OclAny: "cp P \ cp(\X.(P(X::Person)::OclAny).oclIsKindOf(OclAny))" +by(rule cpI1, simp_all add: OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny) +lemma cp_OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_Person: "cp P \ cp(\X.(P(X::OclAny)::Person).oclIsKindOf(OclAny))" +by(rule cpI1, simp_all add: OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person) +lemma cp_OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_OclAny: "cp P \ cp(\X.(P(X::Person)::OclAny).oclIsKindOf(Person))" +by(rule cpI1, simp_all add: OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny) +lemma cp_OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_Person: "cp P \ cp(\X.(P(X::OclAny)::Person).oclIsKindOf(Person))" +by(rule cpI1, simp_all add: OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person) + +lemmas [simp] = + cp_OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_Person + cp_OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_OclAny + cp_OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_Person + cp_OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_OclAny + + cp_OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_OclAny + cp_OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_Person + cp_OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_OclAny + cp_OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_Person + +subsection{* Execution with Invalid or Null as Argument *} + +lemma OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_strict1[simp] : "(invalid::OclAny) .oclIsKindOf(OclAny) = invalid" +by(rule ext, simp add: invalid_def bot_option_def + OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny) + +lemma OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny_strict2[simp] : "(null::OclAny) .oclIsKindOf(OclAny) = true" +by(rule ext, simp add: null_fun_def null_option_def + OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny) + +lemma OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_strict1[simp] : "(invalid::Person) .oclIsKindOf(OclAny) = invalid" +by(rule ext, simp add: bot_option_def invalid_def + OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person) + +lemma OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person_strict2[simp] : "(null::Person) .oclIsKindOf(OclAny) = true" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def + OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person) + +lemma OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_strict1[simp]: "(invalid::OclAny) .oclIsKindOf(Person) = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def + OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny) + +lemma OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny_strict2[simp]: "(null::OclAny) .oclIsKindOf(Person) = true" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def + OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny) + +lemma OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_strict1[simp]: "(invalid::Person) .oclIsKindOf(Person) = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def + OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person) + +lemma OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person_strict2[simp]: "(null::Person) .oclIsKindOf(Person) = true" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def + OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person) + +subsection{* Up Down Casting *} + +lemma actualKind_larger_staticKind: +assumes isdef: "\ \ (\ X)" +shows "\ \ (X::Person) .oclIsKindOf(OclAny) \ true" +using isdef +by(auto simp : bot_option_def + OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person foundation22 foundation16) + +lemma down_cast_kind: +assumes isOclAny: "\ \ \ (X::OclAny) .oclIsKindOf(Person)" +and non_null: "\ \ (\ X)" +shows "\ \ (X .oclAsType(Person)) \ invalid" +using isOclAny non_null +apply(auto simp : bot_fun_def null_fun_def null_option_def bot_option_def null_def invalid_def + OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny foundation22 foundation16 + split: option.split type\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y.split type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n.split) +by(simp add: OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny OclValid_def false_def true_def) + +section{* OclAllInstances *} + +text{* To denote OCL-types occuring in OCL expressions syntactically---as, for example, as +``argument'' of \inlineisar{oclAllInstances()}---we use the inverses of the injection +functions into the object universes; we show that this is sufficient ``characterization.'' *} + +definition "Person \ OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\" +definition "OclAny \ OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_\" +lemmas [simp] = Person_def OclAny_def + +lemma OclAllInstances_generic\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_exec: "OclAllInstances_generic pre_post OclAny = + (\\. Abs_Set_0 \\ Some ` OclAny ` ran (heap (pre_post \)) \\)" +proof - + let ?S1 = "\\. OclAny ` ran (heap (pre_post \))" + let ?S2 = "\\. ?S1 \ - {None}" + have B : "\\. ?S2 \ \ ?S1 \" by auto + have C : "\\. ?S1 \ \ ?S2 \" by(auto simp: OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_\_some) + + show ?thesis by(insert equalityI[OF B C], simp) +qed + +lemma OclAllInstances_at_post\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_exec: "OclAny .allInstances() = + (\\. Abs_Set_0 \\ Some ` OclAny ` ran (heap (snd \)) \\)" +unfolding OclAllInstances_at_post_def +by(rule OclAllInstances_generic\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_exec) + +lemma OclAllInstances_at_pre\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_exec: "OclAny .allInstances@pre() = + (\\. Abs_Set_0 \\ Some ` OclAny ` ran (heap (fst \)) \\) " +unfolding OclAllInstances_at_pre_def +by(rule OclAllInstances_generic\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_exec) + +subsection{* OclIsTypeOf *} + +lemma OclAny_allInstances_generic_oclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y1: +assumes [simp]: "\x. pre_post (x, x) = x" +shows "\\. (\ \ ((OclAllInstances_generic pre_post OclAny)->forAll(X|X .oclIsTypeOf(OclAny))))" + apply(rule_tac x = \\<^sub>0 in exI, simp add: \\<^sub>0_def OclValid_def del: OclAllInstances_generic_def) + apply(simp only: assms OclForall_def refl if_True + OclAllInstances_generic_defined[simplified OclValid_def]) + apply(simp only: OclAllInstances_generic_def) + apply(subst (1 2 3) Abs_Set_0_inverse, simp add: bot_option_def) +by(simp add: OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny) + +lemma OclAny_allInstances_at_post_oclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y1: +"\\. (\ \ (OclAny .allInstances()->forAll(X|X .oclIsTypeOf(OclAny))))" +unfolding OclAllInstances_at_post_def +by(rule OclAny_allInstances_generic_oclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y1, simp) + +lemma OclAny_allInstances_at_pre_oclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y1: +"\\. (\ \ (OclAny .allInstances@pre()->forAll(X|X .oclIsTypeOf(OclAny))))" +unfolding OclAllInstances_at_pre_def +by(rule OclAny_allInstances_generic_oclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y1, simp) + +lemma OclAny_allInstances_generic_oclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y2: +assumes [simp]: "\x. pre_post (x, x) = x" +shows "\\. (\ \ not ((OclAllInstances_generic pre_post OclAny)->forAll(X|X .oclIsTypeOf(OclAny))))" +proof - fix oid a let ?t0 = "\heap = empty(oid \ in\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y (mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid \a\)), + assocs\<^sub>2 = empty, assocs\<^sub>3 = empty\" show ?thesis + apply(rule_tac x = "(?t0, ?t0)" in exI, simp add: OclValid_def del: OclAllInstances_generic_def) + apply(simp only: OclForall_def refl if_True + OclAllInstances_generic_defined[simplified OclValid_def]) + apply(simp only: OclAllInstances_generic_def OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_\_def) + apply(subst (1 2 3) Abs_Set_0_inverse, simp add: bot_option_def) + by(simp add: OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny OclNot_def OclAny_def) +qed + +lemma OclAny_allInstances_at_post_oclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y2: +"\\. (\ \ not (OclAny .allInstances()->forAll(X|X .oclIsTypeOf(OclAny))))" +unfolding OclAllInstances_at_post_def +by(rule OclAny_allInstances_generic_oclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y2, simp) + +lemma OclAny_allInstances_at_pre_oclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y2: +"\\. (\ \ not (OclAny .allInstances@pre()->forAll(X|X .oclIsTypeOf(OclAny))))" +unfolding OclAllInstances_at_pre_def +by(rule OclAny_allInstances_generic_oclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y2, simp) + +lemma Person_allInstances_generic_oclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n: +"\ \ ((OclAllInstances_generic pre_post Person)->forAll(X|X .oclIsTypeOf(Person)))" + apply(simp add: OclValid_def del: OclAllInstances_generic_def) + apply(simp only: OclForall_def refl if_True + OclAllInstances_generic_defined[simplified OclValid_def]) + apply(simp only: OclAllInstances_generic_def) + apply(subst (1 2 3) Abs_Set_0_inverse, simp add: bot_option_def) +by(simp add: OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person) + +lemma Person_allInstances_at_post_oclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n: +"\ \ (Person .allInstances()->forAll(X|X .oclIsTypeOf(Person)))" +unfolding OclAllInstances_at_post_def +by(rule Person_allInstances_generic_oclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n) + +lemma Person_allInstances_at_pre_oclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n: +"\ \ (Person .allInstances@pre()->forAll(X|X .oclIsTypeOf(Person)))" +unfolding OclAllInstances_at_pre_def +by(rule Person_allInstances_generic_oclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n) + +subsection{* OclIsKindOf *} +lemma OclAny_allInstances_generic_oclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y: +"\ \ ((OclAllInstances_generic pre_post OclAny)->forAll(X|X .oclIsKindOf(OclAny)))" + apply(simp add: OclValid_def del: OclAllInstances_generic_def) + apply(simp only: OclForall_def refl if_True + OclAllInstances_generic_defined[simplified OclValid_def]) + apply(simp only: OclAllInstances_generic_def) + apply(subst (1 2 3) Abs_Set_0_inverse, simp add: bot_option_def) +by(simp add: OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny) + +lemma OclAny_allInstances_at_post_oclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y: +"\ \ (OclAny .allInstances()->forAll(X|X .oclIsKindOf(OclAny)))" +unfolding OclAllInstances_at_post_def +by(rule OclAny_allInstances_generic_oclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y) + +lemma OclAny_allInstances_at_pre_oclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y: +"\ \ (OclAny .allInstances@pre()->forAll(X|X .oclIsKindOf(OclAny)))" +unfolding OclAllInstances_at_pre_def +by(rule OclAny_allInstances_generic_oclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y) + +lemma Person_allInstances_generic_oclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y: +"\ \ ((OclAllInstances_generic pre_post Person)->forAll(X|X .oclIsKindOf(OclAny)))" + apply(simp add: OclValid_def del: OclAllInstances_generic_def) + apply(simp only: OclForall_def refl if_True + OclAllInstances_generic_defined[simplified OclValid_def]) + apply(simp only: OclAllInstances_generic_def) + apply(subst (1 2 3) Abs_Set_0_inverse, simp add: bot_option_def) +by(simp add: OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person) + +lemma Person_allInstances_at_post_oclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y: +"\ \ (Person .allInstances()->forAll(X|X .oclIsKindOf(OclAny)))" +unfolding OclAllInstances_at_post_def +by(rule Person_allInstances_generic_oclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y) + +lemma Person_allInstances_at_pre_oclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y: +"\ \ (Person .allInstances@pre()->forAll(X|X .oclIsKindOf(OclAny)))" +unfolding OclAllInstances_at_pre_def +by(rule Person_allInstances_generic_oclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y) + +lemma Person_allInstances_generic_oclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n: +"\ \ ((OclAllInstances_generic pre_post Person)->forAll(X|X .oclIsKindOf(Person)))" + apply(simp add: OclValid_def del: OclAllInstances_generic_def) + apply(simp only: OclForall_def refl if_True + OclAllInstances_generic_defined[simplified OclValid_def]) + apply(simp only: OclAllInstances_generic_def) + apply(subst (1 2 3) Abs_Set_0_inverse, simp add: bot_option_def) +by(simp add: OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person) + +lemma Person_allInstances_at_post_oclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n: +"\ \ (Person .allInstances()->forAll(X|X .oclIsKindOf(Person)))" +unfolding OclAllInstances_at_post_def +by(rule Person_allInstances_generic_oclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n) + +lemma Person_allInstances_at_pre_oclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n: +"\ \ (Person .allInstances@pre()->forAll(X|X .oclIsKindOf(Person)))" +unfolding OclAllInstances_at_pre_def +by(rule Person_allInstances_generic_oclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n) + +section{* The Accessors (any, boss, salary) *} +text{*\label{sec:edm-accessors}*} +text{* Should be generated entirely from a class-diagram. *} + + +subsection{* Definition *} + +definition eval_extract :: "('\,('a::object) option option) val + \ (oid \ ('\,'c::null) val) + \ ('\,'c::null) val" +where "eval_extract X f = (\ \. case X \ of + \ \ invalid \ (* exception propagation *) + | \ \ \ \ invalid \ (* dereferencing null pointer *) + | \\ obj \\ \ f (oid_of obj) \)" +(* TODO: rephrasing as if-then-else and shifting to OCL_state. *) + + +definition deref_oid\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n :: "(\ state \ \ state \ \ state) + \ (type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n \ (\, 'c::null)val) + \ oid + \ (\, 'c::null)val" +where "deref_oid\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n fst_snd f oid = (\\. case (heap (fst_snd \)) oid of + \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n obj \ \ f obj \ + | _ \ invalid \)" + + + +definition deref_oid\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y :: "(\ state \ \ state \ \ state) + \ (type\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y \ (\, 'c::null)val) + \ oid + \ (\, 'c::null)val" +where "deref_oid\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y fst_snd f oid = (\\. case (heap (fst_snd \)) oid of + \ in\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y obj \ \ f obj \ + | _ \ invalid \)" + +text{* pointer undefined in state or not referencing a type conform object representation *} + + +definition "select\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\ f = (\ X. case X of + (mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y _ \) \ null + | (mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y _ \any\) \ f (\x _. \\x\\) any)" + + +definition "select\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\ f = (\ X. case X of + (mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n _ _ \) \ null (* object contains null pointer *) + | (mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n _ _ \boss\) \ f (\x _. \\x\\) boss)" + + +definition "select\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\ f = (\ X. case X of + (mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n _ \ _) \ null + | (mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n _ \salary\ _) \ f (\x _. \\x\\) salary)" + + +definition "in_pre_state = fst" +definition "in_post_state = snd" + +definition "reconst_basetype = (\ convert x. convert x)" + +definition dot\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\ :: "OclAny \ _" ("(1(_).any)" 50) + where "(X).any = eval_extract X + (deref_oid\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y in_post_state + (select\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\ + reconst_basetype))" + +definition dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\ :: "Person \ Person" ("(1(_).boss)" 50) + where "(X).boss = eval_extract X + (deref_oid\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n in_post_state + (select\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\ + (deref_oid\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n in_post_state)))" + +definition dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\ :: "Person \ Integer" ("(1(_).salary)" 50) + where "(X).salary = eval_extract X + (deref_oid\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n in_post_state + (select\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\ + reconst_basetype))" + +definition dot\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\_at_pre :: "OclAny \ _" ("(1(_).any@pre)" 50) + where "(X).any@pre = eval_extract X + (deref_oid\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y in_pre_state + (select\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\ + reconst_basetype))" + +definition dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\_at_pre:: "Person \ Person" ("(1(_).boss@pre)" 50) + where "(X).boss@pre = eval_extract X + (deref_oid\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n in_pre_state + (select\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\ + (deref_oid\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n in_pre_state)))" + +definition dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\_at_pre:: "Person \ Integer" ("(1(_).salary@pre)" 50) + where "(X).salary@pre = eval_extract X + (deref_oid\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n in_pre_state + (select\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\ + reconst_basetype))" + +lemmas [simp] = + dot\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\_def + dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\_def + dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\_def + dot\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\_at_pre_def + dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\_at_pre_def + dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\_at_pre_def + +subsection{* Context Passing *} + +lemmas [simp] = eval_extract_def + +lemma cp_dot\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\: "((X).any) \ = ((\_. X \).any) \" by simp +lemma cp_dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\: "((X).boss) \ = ((\_. X \).boss) \" by simp +lemma cp_dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\: "((X).salary) \ = ((\_. X \).salary) \" by simp + +lemma cp_dot\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\_at_pre: "((X).any@pre) \ = ((\_. X \).any@pre) \" by simp +lemma cp_dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\_at_pre: "((X).boss@pre) \ = ((\_. X \).boss@pre) \" by simp +lemma cp_dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\_at_pre: "((X).salary@pre) \ = ((\_. X \).salary@pre) \" by simp + +lemmas cp_dot\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\_I [simp, intro!]= + cp_dot\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\[THEN allI[THEN allI], + of "\ X _. X" "\ _ \. \", THEN cpI1] +lemmas cp_dot\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\_at_pre_I [simp, intro!]= + cp_dot\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\_at_pre[THEN allI[THEN allI], + of "\ X _. X" "\ _ \. \", THEN cpI1] + +lemmas cp_dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\_I [simp, intro!]= + cp_dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\[THEN allI[THEN allI], + of "\ X _. X" "\ _ \. \", THEN cpI1] +lemmas cp_dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\_at_pre_I [simp, intro!]= + cp_dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\_at_pre[THEN allI[THEN allI], + of "\ X _. X" "\ _ \. \", THEN cpI1] + +lemmas cp_dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\_I [simp, intro!]= + cp_dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\[THEN allI[THEN allI], + of "\ X _. X" "\ _ \. \", THEN cpI1] +lemmas cp_dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\_at_pre_I [simp, intro!]= + cp_dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\_at_pre[THEN allI[THEN allI], + of "\ X _. X" "\ _ \. \", THEN cpI1] + +subsection{* Execution with Invalid or Null as Argument *} + +lemma dot\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\_nullstrict [simp]: "(null).any = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def) +lemma dot\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\_at_pre_nullstrict [simp] : "(null).any@pre = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def) +lemma dot\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\_strict [simp] : "(invalid).any = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def) +lemma dot\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y\\\_at_pre_strict [simp] : "(invalid).any@pre = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def) + + +lemma dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\_nullstrict [simp]: "(null).boss = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def) +lemma dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\_at_pre_nullstrict [simp] : "(null).boss@pre = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def) +lemma dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\_strict [simp] : "(invalid).boss = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def) +lemma dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\_at_pre_strict [simp] : "(invalid).boss@pre = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def) + + +lemma dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\_nullstrict [simp]: "(null).salary = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def) +lemma dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\_at_pre_nullstrict [simp] : "(null).salary@pre = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def) +lemma dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\_strict [simp] : "(invalid).salary = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def) +lemma dot\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n\\\\\\_at_pre_strict [simp] : "(invalid).salary@pre = invalid" +by(rule ext, simp add: null_fun_def null_option_def bot_option_def null_def invalid_def) + + +section{* A Little Infra-structure on Example States *} + +text{* +The example we are defining in this section comes from the figure~\ref{fig:edm1_system-states}. +\begin{figure} +\includegraphics[width=\textwidth]{figures/pre-post.pdf} +\caption{(a) pre-state $\sigma_1$ and + (b) post-state $\sigma_1'$.} +\label{fig:edm1_system-states} +\end{figure} +*} + +definition OclInt1000 ("\\\\") where "OclInt1000 = (\ _ . \\1000\\)" +definition OclInt1200 ("\\\\") where "OclInt1200 = (\ _ . \\1200\\)" +definition OclInt1300 ("\\\\") where "OclInt1300 = (\ _ . \\1300\\)" +definition OclInt1800 ("\\\\") where "OclInt1800 = (\ _ . \\1800\\)" +definition OclInt2600 ("\\\\") where "OclInt2600 = (\ _ . \\2600\\)" +definition OclInt2900 ("\\\\") where "OclInt2900 = (\ _ . \\2900\\)" +definition OclInt3200 ("\\\\") where "OclInt3200 = (\ _ . \\3200\\)" +definition OclInt3500 ("\\\\") where "OclInt3500 = (\ _ . \\3500\\)" + +definition "oid0 \ 0" +definition "oid1 \ 1" +definition "oid2 \ 2" +definition "oid3 \ 3" +definition "oid4 \ 4" +definition "oid5 \ 5" +definition "oid6 \ 6" +definition "oid7 \ 7" +definition "oid8 \ 8" + +definition "person1 \ mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid0 \1300\ \oid1\" +definition "person2 \ mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid1 \1800\ \oid1\" +definition "person3 \ mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid2 None None" +definition "person4 \ mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid3 \2900\ None" +definition "person5 \ mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid4 \3500\ None" +definition "person6 \ mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid5 \2500\ \oid6\" +definition "person7 \ mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid6 \(\3200\, \oid6\)\" +definition "person8 \ mk\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y oid7 None" +definition "person9 \ mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid8 \0\ None" + +definition + "\\<^sub>1 \ \ heap = empty(oid0 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n (mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid0 \1000\ \oid1\)) + (oid1 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n (mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid1 \1200\ None)) + (*oid2*) + (oid3 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n (mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid3 \2600\ \oid4\)) + (oid4 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person5) + (oid5 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n (mk\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n oid5 \2300\ \oid3\)) + (*oid6*) + (*oid7*) + (oid8 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person9), + assocs\<^sub>2 = empty, + assocs\<^sub>3 = empty \" + +definition + "\\<^sub>1' \ \ heap = empty(oid0 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person1) + (oid1 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person2) + (oid2 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person3) + (oid3 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person4) + (*oid4*) + (oid5 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person6) + (oid6 \ in\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y person7) + (oid7 \ in\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y person8) + (oid8 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person9), + assocs\<^sub>2 = empty, + assocs\<^sub>3 = empty \" + +definition "\\<^sub>0 \ \ heap = empty, assocs\<^sub>2 = empty, assocs\<^sub>3 = empty \" + + +lemma basic_\_wff: "WFF(\\<^sub>1,\\<^sub>1')" +by(auto simp: WFF_def \\<^sub>1_def \\<^sub>1'_def + oid0_def oid1_def oid2_def oid3_def oid4_def oid5_def oid6_def oid7_def oid8_def + oid_of_\_def oid_of_type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_def oid_of_type\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_def + person1_def person2_def person3_def person4_def + person5_def person6_def person7_def person8_def person9_def) + +lemma [simp,code_unfold]: "dom (heap \\<^sub>1) = {oid0,oid1,(*,oid2*)oid3,oid4,oid5(*,oid6,oid7*),oid8}" +by(auto simp: \\<^sub>1_def) + +lemma [simp,code_unfold]: "dom (heap \\<^sub>1') = {oid0,oid1,oid2,oid3,(*,oid4*)oid5,oid6,oid7,oid8}" +by(auto simp: \\<^sub>1'_def) + +definition "X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 :: Person \ \ _ .\\ person1 \\" +definition "X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 :: Person \ \ _ .\\ person2 \\" +definition "X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3 :: Person \ \ _ .\\ person3 \\" +definition "X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4 :: Person \ \ _ .\\ person4 \\" +definition "X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5 :: Person \ \ _ .\\ person5 \\" +definition "X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6 :: Person \ \ _ .\\ person6 \\" +definition "X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7 :: OclAny \ \ _ .\\ person7 \\" +definition "X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8 :: OclAny \ \ _ .\\ person8 \\" +definition "X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9 :: Person \ \ _ .\\ person9 \\" + +lemma [code_unfold]: "((x::Person) \ y) = StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t x y" by(simp only: StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n) +lemma [code_unfold]: "((x::OclAny) \ y) = StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t x y" by(simp only: StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y) + +lemmas [simp,code_unfold] = + OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny + OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person + OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny + OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person + + OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny + OclIsTypeOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person + OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny + OclIsTypeOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person + + OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_OclAny + OclIsKindOf\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person + OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_OclAny + OclIsKindOf\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_Person + + +value "\s\<^sub>p\<^sub>r\<^sub>e . (s\<^sub>p\<^sub>r\<^sub>e,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .salary <> \\\\)" +value "\s\<^sub>p\<^sub>r\<^sub>e . (s\<^sub>p\<^sub>r\<^sub>e,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .salary \ \\\\)" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .salary@pre \ \\\\)" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .salary@pre <> \\\\)" +value "\s\<^sub>p\<^sub>r\<^sub>e . (s\<^sub>p\<^sub>r\<^sub>e,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .boss <> X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1)" +value "\s\<^sub>p\<^sub>r\<^sub>e . (s\<^sub>p\<^sub>r\<^sub>e,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .boss .salary \ \\\\)" +value "\s\<^sub>p\<^sub>r\<^sub>e . (s\<^sub>p\<^sub>r\<^sub>e,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .boss .boss <> X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1)" +value "\s\<^sub>p\<^sub>r\<^sub>e . (s\<^sub>p\<^sub>r\<^sub>e,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .boss .boss \ X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2)" +value " (\\<^sub>1,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .boss@pre .salary \ \\\\)" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .boss@pre .salary@pre \ \\\\)" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .boss@pre .salary@pre <> \\\\)" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .boss@pre \ X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2)" +value " (\\<^sub>1,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .boss@pre .boss \ X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2)" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .boss@pre .boss@pre \ null)" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ not(\(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .boss@pre .boss@pre .boss@pre))" + +lemma " (\\<^sub>1,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .oclIsMaintained())" +by(simp add: OclValid_def OclIsMaintained_def + \\<^sub>1_def \\<^sub>1'_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1_def person1_def + oid0_def oid1_def oid2_def oid3_def oid4_def oid5_def oid6_def + oid_of_option_def oid_of_type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_def) + +lemma "\s\<^sub>p\<^sub>r\<^sub>e s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (s\<^sub>p\<^sub>r\<^sub>e,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ ((X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .oclAsType(OclAny) .oclAsType(Person)) \ X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1)" +by(rule up_down_cast_Person_OclAny_Person', simp add: X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1_def) +value "\s\<^sub>p\<^sub>r\<^sub>e s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (s\<^sub>p\<^sub>r\<^sub>e,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .oclIsTypeOf(Person))" +value "\s\<^sub>p\<^sub>r\<^sub>e s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (s\<^sub>p\<^sub>r\<^sub>e,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ not(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .oclIsTypeOf(OclAny))" +value "\s\<^sub>p\<^sub>r\<^sub>e s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (s\<^sub>p\<^sub>r\<^sub>e,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .oclIsKindOf(Person))" +value "\s\<^sub>p\<^sub>r\<^sub>e s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (s\<^sub>p\<^sub>r\<^sub>e,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .oclIsKindOf(OclAny))" +value "\s\<^sub>p\<^sub>r\<^sub>e s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (s\<^sub>p\<^sub>r\<^sub>e,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ not(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .oclAsType(OclAny) .oclIsTypeOf(OclAny))" + + +value "\s\<^sub>p\<^sub>r\<^sub>e . (s\<^sub>p\<^sub>r\<^sub>e,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .salary \ \\\\)" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .salary@pre \ \\\\)" +value "\s\<^sub>p\<^sub>r\<^sub>e . (s\<^sub>p\<^sub>r\<^sub>e,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .boss \ X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2)" +value " (\\<^sub>1,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .boss .salary@pre \ \\\\)" +value " (\\<^sub>1,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .boss .boss@pre \ null)" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .boss@pre \ null)" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .boss@pre <> X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2)" +value " (\\<^sub>1,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .boss@pre <> (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .boss))" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ not(\(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .boss@pre .boss))" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ not(\(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .boss@pre .salary@pre))" +lemma " (\\<^sub>1,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .oclIsMaintained())" +by(simp add: OclValid_def OclIsMaintained_def + \\<^sub>1_def \\<^sub>1'_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2_def person2_def + oid0_def oid1_def oid2_def oid3_def oid4_def oid5_def oid6_def + oid_of_option_def oid_of_type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_def) + + +value "\s\<^sub>p\<^sub>r\<^sub>e . (s\<^sub>p\<^sub>r\<^sub>e,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3 .salary \ null)" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ not(\(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3 .salary@pre))" +value "\s\<^sub>p\<^sub>r\<^sub>e . (s\<^sub>p\<^sub>r\<^sub>e,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3 .boss \ null)" +value "\s\<^sub>p\<^sub>r\<^sub>e . (s\<^sub>p\<^sub>r\<^sub>e,\\<^sub>1') \ not(\(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3 .boss .salary))" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ not(\(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3 .boss@pre))" +lemma " (\\<^sub>1,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3 .oclIsNew())" +by(simp add: OclValid_def OclIsNew_def + \\<^sub>1_def \\<^sub>1'_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3_def person3_def + oid0_def oid1_def oid2_def oid3_def oid4_def oid5_def oid6_def oid8_def + oid_of_option_def oid_of_type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_def) + + +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4 .boss@pre \ X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5)" +value " (\\<^sub>1,\\<^sub>1') \ not(\(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4 .boss@pre .salary))" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4 .boss@pre .salary@pre \ \\\\)" +lemma " (\\<^sub>1,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4 .oclIsMaintained())" +by(simp add: OclValid_def OclIsMaintained_def + \\<^sub>1_def \\<^sub>1'_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4_def person4_def + oid0_def oid1_def oid2_def oid3_def oid4_def oid5_def oid6_def + oid_of_option_def oid_of_type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_def) + + +value "\s\<^sub>p\<^sub>r\<^sub>e . (s\<^sub>p\<^sub>r\<^sub>e,\\<^sub>1') \ not(\(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5 .salary))" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5 .salary@pre \ \\\\)" +value "\s\<^sub>p\<^sub>r\<^sub>e . (s\<^sub>p\<^sub>r\<^sub>e,\\<^sub>1') \ not(\(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5 .boss))" +lemma " (\\<^sub>1,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5 .oclIsDeleted())" +by(simp add: OclNot_def OclValid_def OclIsDeleted_def + \\<^sub>1_def \\<^sub>1'_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5_def person5_def + oid0_def oid1_def oid2_def oid3_def oid4_def oid5_def oid6_def oid7_def oid8_def + oid_of_option_def oid_of_type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_def) + + +(* (* access to an oclany object not yet supported *) value " (\\<^sub>1,\\<^sub>1') \ ((X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6 .boss .salary) \ \\\\ )"*) +value "\s\<^sub>p\<^sub>r\<^sub>e . (s\<^sub>p\<^sub>r\<^sub>e,\\<^sub>1') \ not(\(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6 .boss .salary@pre))" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6 .boss@pre \ X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4)" +value " (\\<^sub>1,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6 .boss@pre .salary \ \\\\)" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6 .boss@pre .salary@pre \ \\\\)" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6 .boss@pre .boss@pre \ X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5)" +lemma " (\\<^sub>1,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6 .oclIsMaintained())" +by(simp add: OclValid_def OclIsMaintained_def + \\<^sub>1_def \\<^sub>1'_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6_def person6_def + oid0_def oid1_def oid2_def oid3_def oid4_def oid5_def oid6_def + oid_of_option_def oid_of_type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_def) + + +(* (* access to an oclany object not yet supported *) value " (\\<^sub>1,\\<^sub>1') \ ((X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7 .oclAsType(Person) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6 .boss)))" *) +(* (* access to an oclany object not yet supported *) value " (\\<^sub>1,\\<^sub>1') \ ((X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7 .oclAsType(Person) .boss) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7 .oclAsType(Person)) )" *) +(* (* access to an oclany object not yet supported *) value " (\\<^sub>1,\\<^sub>1') \ ((X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7 .oclAsType(Person) .boss .salary) \ \\\\ )" *) +value "\s\<^sub>p\<^sub>r\<^sub>e s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (s\<^sub>p\<^sub>r\<^sub>e,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ \(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7 .oclAsType(Person))" +value "\ s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (\\<^sub>1,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ not(\(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7 .oclAsType(Person) .boss@pre))" +lemma "\s\<^sub>p\<^sub>r\<^sub>e s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (s\<^sub>p\<^sub>r\<^sub>e,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ ((X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7 .oclAsType(Person) .oclAsType(OclAny) + .oclAsType(Person)) + \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7 .oclAsType(Person)))" +by(rule up_down_cast_Person_OclAny_Person', simp add: X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7_def OclValid_def valid_def person7_def) +lemma " (\\<^sub>1,\\<^sub>1') \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7 .oclIsNew())" +by(simp add: OclValid_def OclIsNew_def + \\<^sub>1_def \\<^sub>1'_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7_def person7_def + oid0_def oid1_def oid2_def oid3_def oid4_def oid5_def oid6_def oid8_def + oid_of_option_def oid_of_type\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_def) + + +value "\s\<^sub>p\<^sub>r\<^sub>e s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (s\<^sub>p\<^sub>r\<^sub>e,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8 <> X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7)" +value "\s\<^sub>p\<^sub>r\<^sub>e s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (s\<^sub>p\<^sub>r\<^sub>e,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ not(\(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8 .oclAsType(Person)))" +value "\s\<^sub>p\<^sub>r\<^sub>e s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (s\<^sub>p\<^sub>r\<^sub>e,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8 .oclIsTypeOf(OclAny))" +value "\s\<^sub>p\<^sub>r\<^sub>e s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (s\<^sub>p\<^sub>r\<^sub>e,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ not(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8 .oclIsTypeOf(Person))" +value "\s\<^sub>p\<^sub>r\<^sub>e s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (s\<^sub>p\<^sub>r\<^sub>e,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ not(X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8 .oclIsKindOf(Person))" +value "\s\<^sub>p\<^sub>r\<^sub>e s\<^sub>p\<^sub>o\<^sub>s\<^sub>t. (s\<^sub>p\<^sub>r\<^sub>e,s\<^sub>p\<^sub>o\<^sub>s\<^sub>t) \ (X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8 .oclIsKindOf(OclAny))" + + +lemma \_modifiedonly: "(\\<^sub>1,\\<^sub>1') \ (Set{ X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .oclAsType(OclAny) + , X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .oclAsType(OclAny) + (*, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3 .oclAsType(OclAny)*) + , X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4 .oclAsType(OclAny) + (*, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5 .oclAsType(OclAny)*) + , X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6 .oclAsType(OclAny) + (*, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7 .oclAsType(OclAny)*) + (*, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8 .oclAsType(OclAny)*) + (*, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9 .oclAsType(OclAny)*)}->oclIsModifiedOnly())" + apply(simp add: OclIsModifiedOnly_def OclValid_def + oid0_def oid1_def oid2_def oid3_def oid4_def oid5_def oid6_def oid7_def oid8_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9_def + person1_def person2_def person3_def person4_def + person5_def person6_def person7_def person8_def person9_def + image_def) + apply(simp add: OclIncluding_rep_set mtSet_rep_set null_option_def bot_option_def) + apply(simp add: oid_of_option_def oid_of_type\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_def, clarsimp) + apply(simp add: \\<^sub>1_def \\<^sub>1'_def + oid0_def oid1_def oid2_def oid3_def oid4_def oid5_def oid6_def oid7_def oid8_def) +done + +lemma "(\\<^sub>1,\\<^sub>1') \ ((X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9 @pre (\x. \OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\ x\)) \ X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9)" +by(simp add: OclSelf_at_pre_def \\<^sub>1_def oid_of_option_def oid_of_type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9_def person9_def oid8_def OclValid_def StrongEq_def OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\_def) + +lemma "(\\<^sub>1,\\<^sub>1') \ ((X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9 @post (\x. \OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\ x\)) \ X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9)" +by(simp add: OclSelf_at_post_def \\<^sub>1'_def oid_of_option_def oid_of_type\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9_def person9_def oid8_def OclValid_def StrongEq_def OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\_def) + +lemma "(\\<^sub>1,\\<^sub>1') \ (((X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9 .oclAsType(OclAny)) @pre (\x. \OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_\ x\)) \ + ((X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9 .oclAsType(OclAny)) @post (\x. \OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_\ x\)))" +proof - + + have including4 : "\a b c d \. + Set{\\. \\a\\, \\. \\b\\, \\. \\c\\, \\. \\d\\} \ = Abs_Set_0 \\ {\\a\\, \\b\\, \\c\\, \\d\\} \\" + apply(subst abs_rep_simp'[symmetric], simp) + by(simp add: OclIncluding_rep_set mtSet_rep_set) + + have excluding1: "\S a b c d e \. + (\_. Abs_Set_0 \\ {\\a\\, \\b\\, \\c\\, \\d\\} \\)->excluding(\\. \\e\\) \ = + Abs_Set_0 \\ {\\a\\, \\b\\, \\c\\, \\d\\} - {\\e\\} \\" + apply(simp add: OclExcluding_def) + apply(simp add: defined_def OclValid_def false_def true_def + bot_fun_def bot_Set_0_def null_fun_def null_Set_0_def) + apply(rule conjI) + apply(rule impI, subst (asm) Abs_Set_0_inject) apply( simp add: bot_option_def)+ + apply(rule conjI) + apply(rule impI, subst (asm) Abs_Set_0_inject) apply( simp add: bot_option_def null_option_def)+ + apply(subst Abs_Set_0_inverse, simp add: bot_option_def, simp) + done + + show ?thesis + apply(rule framing[where X = "Set{ X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .oclAsType(OclAny) + , X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .oclAsType(OclAny) + (*, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3 .oclAsType(OclAny)*) + , X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4 .oclAsType(OclAny) + (*, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5 .oclAsType(OclAny)*) + , X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6 .oclAsType(OclAny) + (*, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7 .oclAsType(OclAny)*) + (*, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8 .oclAsType(OclAny)*) + (*, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9 .oclAsType(OclAny)*)}"]) + apply(cut_tac \_modifiedonly) + apply(simp only: OclValid_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9_def + person1_def person2_def person3_def person4_def + person5_def person6_def person7_def person8_def person9_def + OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_Person) + apply(subst cp_OclIsModifiedOnly, subst cp_OclExcluding, + subst (asm) cp_OclIsModifiedOnly, simp add: including4 excluding1) + + apply(simp only: X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9_def + person1_def person2_def person3_def person4_def + person5_def person6_def person7_def person8_def person9_def) + apply(simp add: OclIncluding_rep_set mtSet_rep_set + oid0_def oid1_def oid2_def oid3_def oid4_def oid5_def oid6_def oid7_def oid8_def) + apply(simp add: StrictRefEq\<^sub>O\<^sub>b\<^sub>j\<^sub>e\<^sub>c\<^sub>t_def oid_of_option_def oid_of_type\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_def OclNot_def OclValid_def + null_option_def bot_option_def) + done +qed + +lemma perm_\\<^sub>1' : "\\<^sub>1' = \ heap = empty + (oid8 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person9) + (oid7 \ in\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y person8) + (oid6 \ in\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y person7) + (oid5 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person6) + (*oid4*) + (oid3 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person4) + (oid2 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person3) + (oid1 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person2) + (oid0 \ in\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n person1) + , assocs\<^sub>2 = assocs\<^sub>2 \\<^sub>1' + , assocs\<^sub>3 = assocs\<^sub>3 \\<^sub>1' \" +proof - + note P = fun_upd_twist + show ?thesis + apply(simp add: \\<^sub>1'_def + oid0_def oid1_def oid2_def oid3_def oid4_def oid5_def oid6_def oid7_def oid8_def) + apply(subst (1) P, simp) + apply(subst (2) P, simp) apply(subst (1) P, simp) + apply(subst (3) P, simp) apply(subst (2) P, simp) apply(subst (1) P, simp) + apply(subst (4) P, simp) apply(subst (3) P, simp) apply(subst (2) P, simp) apply(subst (1) P, simp) + apply(subst (5) P, simp) apply(subst (4) P, simp) apply(subst (3) P, simp) apply(subst (2) P, simp) apply(subst (1) P, simp) + apply(subst (6) P, simp) apply(subst (5) P, simp) apply(subst (4) P, simp) apply(subst (3) P, simp) apply(subst (2) P, simp) apply(subst (1) P, simp) + apply(subst (7) P, simp) apply(subst (6) P, simp) apply(subst (5) P, simp) apply(subst (4) P, simp) apply(subst (3) P, simp) apply(subst (2) P, simp) apply(subst (1) P, simp) + by(simp) +qed + +declare const_ss [simp] + +lemma "\\\<^sub>1. + (\\<^sub>1,\\<^sub>1') \ (Person .allInstances() \ Set{ X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4(*, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5*), X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6, + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7 .oclAsType(Person)(*, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8*), X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9 })" + apply(subst perm_\\<^sub>1') + apply(simp only: oid0_def oid1_def oid2_def oid3_def oid4_def oid5_def oid6_def oid7_def oid8_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9_def + person7_def) + apply(subst state_update_vs_allInstances_at_post_tc, simp, simp add: OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\_def, simp, rule const_StrictRefEq\<^sub>S\<^sub>e\<^sub>t_including, simp, simp, simp, rule OclIncluding_cong, simp, simp) + apply(subst state_update_vs_allInstances_at_post_tc, simp, simp add: OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\_def, simp, rule const_StrictRefEq\<^sub>S\<^sub>e\<^sub>t_including, simp, simp, simp, rule OclIncluding_cong, simp, simp) + apply(subst state_update_vs_allInstances_at_post_tc, simp, simp add: OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\_def, simp, rule const_StrictRefEq\<^sub>S\<^sub>e\<^sub>t_including, simp, simp, simp, rule OclIncluding_cong, simp, simp) + apply(subst state_update_vs_allInstances_at_post_tc, simp, simp add: OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\_def, simp, rule const_StrictRefEq\<^sub>S\<^sub>e\<^sub>t_including, simp, simp, simp, rule OclIncluding_cong, simp, simp) + apply(subst state_update_vs_allInstances_at_post_tc, simp, simp add: OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\_def, simp, rule const_StrictRefEq\<^sub>S\<^sub>e\<^sub>t_including, simp, simp, simp, rule OclIncluding_cong, simp, simp) + apply(subst state_update_vs_allInstances_at_post_tc, simp, simp add: OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\_def, simp, rule const_StrictRefEq\<^sub>S\<^sub>e\<^sub>t_including, simp, simp, simp, rule OclIncluding_cong, simp, simp) + apply(subst state_update_vs_allInstances_at_post_ntc, simp, simp add: OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\_def + person8_def, simp, rule const_StrictRefEq\<^sub>S\<^sub>e\<^sub>t_including, simp, simp, simp) + apply(subst state_update_vs_allInstances_at_post_tc, simp, simp add: OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\_def, simp, rule const_StrictRefEq\<^sub>S\<^sub>e\<^sub>t_including, simp, simp, simp, rule OclIncluding_cong, simp, simp) + apply(rule state_update_vs_allInstances_at_post_empty) +by(simp_all add: OclAsType\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n_\_def) + +lemma "\\\<^sub>1. + (\\<^sub>1,\\<^sub>1') \ (OclAny .allInstances() \ Set{ X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1 .oclAsType(OclAny), X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2 .oclAsType(OclAny), + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3 .oclAsType(OclAny), X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4 .oclAsType(OclAny) + (*, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5*), X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6 .oclAsType(OclAny), + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8, X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9 .oclAsType(OclAny) })" + apply(subst perm_\\<^sub>1') + apply(simp only: oid0_def oid1_def oid2_def oid3_def oid4_def oid5_def oid6_def oid7_def oid8_def + X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n1_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n2_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n3_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n4_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n5_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n6_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n7_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n8_def X\<^sub>P\<^sub>e\<^sub>r\<^sub>s\<^sub>o\<^sub>n9_def + person1_def person2_def person3_def person4_def person5_def person6_def person9_def) + apply(subst state_update_vs_allInstances_at_post_tc, simp, simp add: OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_\_def, simp, rule const_StrictRefEq\<^sub>S\<^sub>e\<^sub>t_including, simp, simp, simp, rule OclIncluding_cong, simp, simp)+ + apply(rule state_update_vs_allInstances_at_post_empty) +by(simp_all add: OclAsType\<^sub>O\<^sub>c\<^sub>l\<^sub>A\<^sub>n\<^sub>y_\_def) + +end