Theory UML_Integer

(*****************************************************************************
 * Featherweight-OCL --- A Formal Semantics for UML-OCL Version OCL 2.5
 *                       for the OMG Standard.
 *                       http://www.brucker.ch/projects/hol-testgen/
 *
 * UML_Integer.thy --- Library definitions.
 * This file is part of HOL-TestGen.
 *
 * Copyright (c) 2012-2015 Université Paris-Saclay, Univ. Paris-Sud, France
 *               2013-2015 IRT SystemX, France
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *
 *     * Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials provided
 *       with the distribution.
 *
 *     * Neither the name of the copyright holders nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ******************************************************************************)

theory  UML_Integer
imports "../UML_PropertyProfiles"
begin

section‹Basic Type Integer: Operations›

subsection‹Fundamental Predicates on Integers: Strict Equality \label{sec:integer-strict-eq}›

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:›
overloading StrictRefEq ≡ "StrictRefEq :: [('𝔄)Integer,('𝔄)Integer] ⇒ ('𝔄)Boolean"
begin
  definition StrictRefEqInteger[code_unfold] :
    "(x::('𝔄)Integer) ≐ y ≡ λ τ. if (υ x) τ = true τ ∧ (υ y) τ = true τ
                                  then (x ≜ y) τ
                                  else invalid τ"
end

text‹Property proof in terms of @{term "profile_binStrongEq_v_v"}›
interpretation  StrictRefEqInteger : profile_binStrongEq_v_v "λ x y. (x::('𝔄)Integer) ≐ y" 
         by unfold_locales (auto simp: StrictRefEqInteger)

subsection‹Basic Integer Constants›

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⌋⌋)"
text‹Etc.›
text_raw‹\isatagafp›
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)

text_raw‹\endisatagafp›

subsection‹Arithmetical Operations›

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 OclAddInteger ::"('𝔄)Integer ⇒ ('𝔄)Integer ⇒ ('𝔄)Integer" (infix ‹+int› 40)
where "x +int y ≡ λ τ. if (δ x) τ = true τ ∧ (δ y) τ = true τ
                       then ⌊⌊⌈⌈x τ⌉⌉ + ⌈⌈y τ⌉⌉⌋⌋
                       else invalid τ "
interpretation OclAddInteger : profile_bind_d "(+int)" "λ x y. ⌊⌊⌈⌈x⌉⌉ + ⌈⌈y⌉⌉⌋⌋"
         by unfold_locales (auto simp:OclAddInteger_def bot_option_def null_option_def)

  
definition OclMinusInteger ::"('𝔄)Integer ⇒ ('𝔄)Integer ⇒ ('𝔄)Integer" (infix ‹-int› 41)
where "x -int y ≡ λ τ. if (δ x) τ = true τ ∧ (δ y) τ = true τ
                       then ⌊⌊⌈⌈x τ⌉⌉ - ⌈⌈y τ⌉⌉⌋⌋
                       else invalid τ "
interpretation OclMinusInteger : profile_bind_d "(-int)" "λ x y. ⌊⌊⌈⌈x⌉⌉ - ⌈⌈y⌉⌉⌋⌋"
         by   unfold_locales  (auto simp:OclMinusInteger_def bot_option_def null_option_def)

                       
definition OclMultInteger ::"('𝔄)Integer ⇒ ('𝔄)Integer ⇒ ('𝔄)Integer" (infix ‹*int› 45)
where "x *int y ≡ λ τ. if (δ x) τ = true τ ∧ (δ y) τ = true τ
                       then ⌊⌊⌈⌈x τ⌉⌉ * ⌈⌈y τ⌉⌉⌋⌋
                       else invalid τ"
interpretation OclMultInteger : profile_bind_d "OclMultInteger" "λ x y. ⌊⌊⌈⌈x⌉⌉ * ⌈⌈y⌉⌉⌋⌋"
         by   unfold_locales  (auto simp:OclMultInteger_def bot_option_def null_option_def)
          
text‹Here is the special case of division, which is defined as invalid for division
by zero.›
definition OclDivisionInteger ::"('𝔄)Integer ⇒ ('𝔄)Integer ⇒ ('𝔄)Integer" (infix ‹divint› 45)
where "x divint y ≡ λ τ. if (δ x) τ = true τ ∧ (δ y) τ = true τ
                       then if y τ ≠ OclInt0 τ then ⌊⌊⌈⌈x τ⌉⌉ div ⌈⌈y τ⌉⌉⌋⌋ else invalid τ 
                       else invalid τ "
(* TODO: special locale setup.*)

definition OclModulusInteger ::"('𝔄)Integer ⇒ ('𝔄)Integer ⇒ ('𝔄)Integer" (infix ‹modint› 45)
where "x modint y ≡ λ τ. if (δ x) τ = true τ ∧ (δ y) τ = true τ
                       then if y τ ≠ OclInt0 τ then ⌊⌊⌈⌈x τ⌉⌉ mod ⌈⌈y τ⌉⌉⌋⌋ else invalid τ 
                       else invalid τ "
(* TODO: special locale setup.*)
                       
                       
definition OclLessInteger ::"('𝔄)Integer ⇒ ('𝔄)Integer ⇒ ('𝔄)Boolean" (infix ‹<int› 35)
where "x <int y ≡ λ τ. if (δ x) τ = true τ ∧ (δ y) τ = true τ
                       then ⌊⌊⌈⌈x τ⌉⌉ < ⌈⌈y τ⌉⌉⌋⌋
                       else invalid τ "
interpretation OclLessInteger : profile_bind_d "(<int)" "λ x y. ⌊⌊⌈⌈x⌉⌉ < ⌈⌈y⌉⌉⌋⌋"
         by   unfold_locales  (auto simp:OclLessInteger_def bot_option_def null_option_def)

definition OclLeInteger ::"('𝔄)Integer ⇒ ('𝔄)Integer ⇒ ('𝔄)Boolean" (infix ‹≤int› 35)
where "x ≤int y ≡ λ τ. if (δ x) τ = true τ ∧ (δ y) τ = true τ
                       then ⌊⌊⌈⌈x τ⌉⌉ ≤ ⌈⌈y τ⌉⌉⌋⌋
                       else invalid τ "
interpretation OclLeInteger : profile_bind_d "(≤int)" "λ x y. ⌊⌊⌈⌈x⌉⌉ ≤ ⌈⌈y⌉⌉⌋⌋"
         by   unfold_locales  (auto simp:OclLeInteger_def bot_option_def null_option_def)

subsubsection‹Basic Properties›

lemma OclAddInteger_commute: "(X +int Y) = (Y +int X)"
  by(rule ext,auto simp:true_def false_def OclAddInteger_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 OclAddInteger_zero1[simp,code_unfold] :
"(x +int 𝟬) = (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 +int 𝟬) τ = (if υ x and not (δ x) then invalid else x endif) τ"
   apply(subst OclIf_true', simp add: OclValid_def)
  by (metis OclAddInteger_def OclNot_defargs OclValid_def foundation5 foundation9)
 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 foundation16)
   apply(rename_tac x', case_tac x', metis bot_option_def foundation16 null_option_def)
  by(simp)
  show "(x +int 𝟬) τ = (if υ x and not (δ x) then invalid else x endif) τ"
    when "τ ⊨ not (υ x and not (δ x))"
   apply(insert that, subst OclIf_false', simp, simp add: A, auto simp: OclAddInteger_def OclInt0_def)
     (* *)
     apply(simp add: foundation16'[simplified OclValid_def])
    apply(simp add: B)
  by(simp add: OclValid_def)
qed(metis OclValid_def defined5 defined6 defined_and_I defined_not_I foundation9)

lemma OclAddInteger_zero2[simp,code_unfold] :
"(𝟬 +int x) = (if υ x and not (δ x) then invalid else x endif)"
by(subst OclAddInteger_commute, simp)

(* TODO Basic proproperties for multiplication, division, modulus. *)



subsection‹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"}.›

Assert "τ ⊨ ( 𝟵 ≤int 𝟭𝟬 )"
Assert "τ ⊨ (( 𝟰 +int 𝟰 ) ≤int 𝟭𝟬 )"
Assert "τ |≠ (( 𝟰 +int ( 𝟰 +int 𝟰 )) <int 𝟭𝟬 )"
Assert "τ ⊨ not (υ (null +int 𝟭)) "
Assert "τ ⊨ (((𝟵 *int 𝟰) divint 𝟭𝟬) ≤int  𝟰) "
Assert "τ ⊨ not (δ (𝟭 divint 𝟬)) "
Assert "τ ⊨ not (υ (𝟭 divint 𝟬)) "



lemma integer_non_null [simp]: "((λ_. ⌊⌊n⌋⌋) ≐ (null::('𝔄)Integer)) = false"
by(rule ext,auto simp: StrictRefEqInteger 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: StrictRefEqInteger 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)


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 Integer›

Assert "τ ⊨ ((𝟬 <int 𝟮) and (𝟬 <int 𝟭))"

Assert "τ ⊨ 𝟭 <> 𝟮"
Assert "τ ⊨ 𝟮 <> 𝟭"
Assert "τ ⊨ 𝟮 ≐ 𝟮"

Assert "τ ⊨ υ 𝟰"
Assert "τ ⊨ δ 𝟰"
Assert "τ ⊨ υ (null::('𝔄)Integer)"
Assert "τ ⊨ (invalid ≜ invalid)"
Assert "τ ⊨ (null ≜ null)"
Assert "τ ⊨ (𝟰 ≜ 𝟰)"
Assert "τ |≠ (𝟵 ≜ 𝟭𝟬)"
Assert "τ |≠ (invalid ≜ 𝟭𝟬)"
Assert "τ |≠ (null ≜ 𝟭𝟬)"
Assert "τ |≠ (invalid ≐ (invalid::('𝔄)Integer))"   (* Without typeconstraint not executable.*)
Assert "τ |≠ υ (invalid ≐ (invalid::('𝔄)Integer))" (* Without typeconstraint not executable.*)
Assert "τ |≠ (invalid <> (invalid::('𝔄)Integer))"   (* Without typeconstraint not executable.*)
Assert "τ |≠ υ (invalid <> (invalid::('𝔄)Integer))" (* Without typeconstraint not executable.*)
Assert "τ ⊨ (null ≐ (null::('𝔄)Integer) )" (* Without typeconstraint not executable.*)
Assert "τ ⊨ (null ≐ (null::('𝔄)Integer) )" (* Without typeconstraint not executable.*)
Assert "τ ⊨ (𝟰 ≐ 𝟰)"
Assert "τ |≠ (𝟰 <> 𝟰)"
Assert "τ |≠ (𝟰 ≐ 𝟭𝟬)"
Assert "τ ⊨ (𝟰 <> 𝟭𝟬)"
Assert "τ |≠ (𝟬 <int null)"
Assert "τ |≠ (δ (𝟬 <int null))"


end