(* Title: Safe OCL
Author: Denis Nikiforov, March 2019
Maintainer: Denis Nikiforov <denis.nikif at gmail.com>
License: LGPL
*)
(* TODO: There are a lot of similar lemmas in the theory.
They should be generalized *)
section ‹Tuples›
theory Tuple
imports Finite_Map_Ext Transitive_Closure_Ext
begin
subsection ‹Definitions›
abbreviation "subtuple f xm ym ≡ fmrel_on_fset (fmdom ym) f xm ym"
abbreviation "strict_subtuple f xm ym ≡ subtuple f xm ym ∧ xm ≠ ym"
(*** Helper Lemmas **********************************************************)
subsection ‹Helper Lemmas›
lemma fmrel_to_subtuple:
"fmrel r xm ym ==> subtuple r xm ym"
unfolding fmrel_on_fset_fmrel_restrict by blast
lemma subtuple_eq_fmrel_fmrestrict_fset:
"subtuple r xm ym = fmrel r (fmrestrict_fset (fmdom ym) xm) ym"
by (simp add: fmrel_on_fset_fmrel_restrict)
lemma subtuple_fmdom:
"subtuple f xm ym ==>
subtuple g ym xm ==>
fmdom xm = fmdom ym"
by (meson fmrel_on_fset_fmdom fset_eqI)
(*** Basic Properties *******************************************************)
subsection ‹Basic Properties›
lemma subtuple_refl:
"reflp R ==> subtuple R xm xm"
by (simp add: fmrel_on_fsetI option.rel_reflp reflpD)
lemma subtuple_mono [mono]:
"(∧x y. x ∈ fmran' xm ==> y ∈ fmran' ym ==> f x y ⟶ g x y) ==>
subtuple f xm ym ⟶ subtuple g xm ym"
apply (auto)
apply (rule fmrel_on_fsetI)
apply (drule_tac ?P="f" and ?m="xm" and ?n="ym" in fmrel_on_fsetD, simp)
apply (erule option.rel_cases, simp)
by (auto simp add: option.rel_sel fmran'I)
lemma strict_subtuple_mono [mono]:
"(∧x y. x ∈ fmran' xm ==> y ∈ fmran' ym ==> f x y ⟶ g x y) ==>
strict_subtuple f xm ym ⟶ strict_subtuple g xm ym"
using subtuple_mono by blast
lemma subtuple_antisym:
assumes "subtuple (λx y. f x y ∨ x = y) xm ym"
assumes "subtuple (λx y. f x y ∧ ¬ f y x ∨ x = y) ym xm"
shows "xm = ym"
proof (rule fmap_ext)
fix x
from assms have "fmdom xm = fmdom ym"
using subtuple_fmdom by blast
with assms have "fmrel (λx y. f x y ∨ x = y) xm ym"
and "fmrel (λx y. f x y ∧ ¬ f y x ∨ x = y) ym xm"
by (metis (mono_tags, lifting) fmrel_code fmrel_on_fset_alt_def)+
thus "fmlookup xm x = fmlookup ym x"
apply (erule_tac ?x="x" in fmrel_cases)
by (erule_tac ?x="x" in fmrel_cases, auto)+
qed
lemma strict_subtuple_antisym:
"strict_subtuple (λx y. f x y ∨ x = y) xm ym ==>
strict_subtuple (λx y. f x y ∧ ¬ f y x ∨ x = y) ym xm ==> False"
by (auto simp add: subtuple_antisym)
lemma subtuple_acyclic:
assumes "acyclicP_on (fmran' xm) P"
assumes "subtuple (λx y. P x y ∨ x = y)++ xm ym"
assumes "subtuple (λx y. P x y ∨ x = y) ym xm"
shows "xm = ym"
proof (rule fmap_ext)
fix x
from assms have fmdom_eq: "fmdom xm = fmdom ym"
using subtuple_fmdom by blast
have "∧x a b. acyclicP_on (fmran' xm) P ==>
fmlookup xm x = Some a ==>
fmlookup ym x = Some b ==>
P** a b ==> P b a ∨ a = b ==> a = b"
by (meson Nitpick.tranclp_unfold fmran'I rtranclp_into_tranclp1)
moreover from fmdom_eq assms(2) have "fmrel P** xm ym"
unfolding fmrel_on_fset_fmrel_restrict apply auto
by (metis fmrestrict_fset_dom)
moreover from fmdom_eq assms(3) have "fmrel (λx y. P x y ∨ x = y) ym xm"
unfolding fmrel_on_fset_fmrel_restrict apply auto
by (metis fmrestrict_fset_dom)
ultimately show "fmlookup xm x = fmlookup ym x"
apply (erule_tac ?x="x" in fmrel_cases)
apply (erule_tac ?x="x" in fmrel_cases, simp_all)+
using assms(1) by blast
qed
lemma subtuple_acyclic':
assumes "acyclicP_on (fmran' ym) P"
assumes "subtuple (λx y. P x y ∨ x = y)++ xm ym"
assumes "subtuple (λx y. P x y ∨ x = y) ym xm"
shows "xm = ym"
proof (rule fmap_ext)
fix x
from assms have fmdom_eq: "fmdom xm = fmdom ym"
using subtuple_fmdom by blast
have "∧x a b. acyclicP_on (fmran' ym) P ==>
fmlookup xm x = Some a ==>
fmlookup ym x = Some b ==>
P** a b ==> P b a ∨ a = b ==> a = b"
by (meson Nitpick.tranclp_unfold fmran'I rtranclp_into_tranclp2)
moreover from fmdom_eq assms(2) have "fmrel P** xm ym"
unfolding fmrel_on_fset_fmrel_restrict apply auto
by (metis fmrestrict_fset_dom)
moreover from fmdom_eq assms(3) have "fmrel (λx y. P x y ∨ x = y) ym xm"
unfolding fmrel_on_fset_fmrel_restrict apply auto
by (metis fmrestrict_fset_dom)
ultimately show "fmlookup xm x = fmlookup ym x"
apply (erule_tac ?x="x" in fmrel_cases)
apply (erule_tac ?x="x" in fmrel_cases, simp_all)+
using assms(1) by blast
qed
lemma subtuple_acyclic'':
"acyclicP_on (fmran' ym) R ==>
subtuple R** xm ym ==>
subtuple R ym xm ==>
xm = ym"
by (metis (no_types, lifting) subtuple_acyclic' subtuple_mono tranclp_eq_rtranclp)
lemma strict_subtuple_trans:
"acyclicP_on (fmran' xm) P ==>
strict_subtuple (λx y. P x y ∨ x = y)++ xm ym ==>
strict_subtuple (λx y. P x y ∨ x = y) ym zm ==>
strict_subtuple (λx y. P x y ∨ x = y)++ xm zm"
apply auto
apply (rule fmrel_on_fset_trans, auto)
by (drule_tac ?ym="ym" in subtuple_acyclic; auto)
lemma strict_subtuple_trans':
"acyclicP_on (fmran' zm) P ==>
strict_subtuple (λx y. P x y ∨ x = y) xm ym ==>
strict_subtuple (λx y. P x y ∨ x = y)++ ym zm ==>
strict_subtuple (λx y. P x y ∨ x = y)++ xm zm"
apply auto
apply (rule fmrel_on_fset_trans, auto)
by (drule_tac ?xm="ym" in subtuple_acyclic'; auto)
lemma strict_subtuple_trans'':
"acyclicP_on (fmran' zm) R ==>
strict_subtuple R xm ym ==>
strict_subtuple R** ym zm ==>
strict_subtuple R** xm zm"
apply auto
apply (rule fmrel_on_fset_trans, auto)
by (drule_tac ?xm="ym" in subtuple_acyclic''; auto)
lemma strict_subtuple_trans''':
"acyclicP_on (fmran' zm) P ==>
strict_subtuple (λx y. P x y ∨ x = y) xm ym ==>
strict_subtuple (λx y. P x y ∨ x = y)** ym zm ==>
strict_subtuple (λx y. P x y ∨ x = y)** xm zm"
apply auto
apply (rule fmrel_on_fset_trans, auto)
by (drule_tac ?xm="ym" in subtuple_acyclic'; auto)
lemma subtuple_fmmerge2 [intro]:
"(∧x y. x ∈ fmran' xm ==> f x (g x y)) ==>
subtuple f xm (fmmerge g xm ym)"
by (rule_tac ?S="fmdom ym" in fmrel_on_fsubset; auto)
(*** Transitive Closures ****************************************************)
subsection ‹Transitive Closures›
lemma trancl_to_subtuple:
"(subtuple r)++ xm ym ==>
subtuple r++ xm ym"
apply (induct rule: tranclp_induct)
apply (metis subtuple_mono tranclp.r_into_trancl)
by (rule fmrel_on_fset_trans; auto)
lemma rtrancl_to_subtuple:
"(subtuple r)** xm ym ==>
subtuple r** xm ym"
apply (induct rule: rtranclp_induct)
apply (simp add: fmap.rel_refl_strong fmrel_to_subtuple)
by (rule fmrel_on_fset_trans; auto)
lemma fmrel_to_subtuple_trancl:
"reflp r ==>
(fmrel r)++ (fmrestrict_fset (fmdom ym) xm) ym ==>
(subtuple r)++ xm ym"
apply (frule trancl_to_fmrel)
apply (rule_tac ?r="r" in fmrel_tranclp_induct, auto)
apply (metis (no_types, lifting) fmrel_fmdom_eq
subtuple_eq_fmrel_fmrestrict_fset tranclp.r_into_trancl)
by (meson fmrel_to_subtuple tranclp.simps)
lemma subtuple_to_trancl:
"reflp r ==>
subtuple r++ xm ym ==>
(subtuple r)++ xm ym"
apply (rule fmrel_to_subtuple_trancl)
unfolding fmrel_on_fset_fmrel_restrict
by (simp_all add: fmrel_to_trancl)
lemma trancl_to_strict_subtuple:
"acyclicP_on (fmran' ym) R ==>
(strict_subtuple R)++ xm ym ==>
strict_subtuple R** xm ym"
apply (erule converse_tranclp_induct)
apply (metis r_into_rtranclp strict_subtuple_mono)
using strict_subtuple_trans'' by blast
lemma trancl_to_strict_subtuple':
"acyclicP_on (fmran' ym) R ==>
(strict_subtuple (λx y. R x y ∨ x = y))++ xm ym ==>
strict_subtuple (λx y. R x y ∨ x = y)** xm ym"
apply (erule converse_tranclp_induct)
apply (metis (no_types, lifting) r_into_rtranclp strict_subtuple_mono)
using strict_subtuple_trans''' by blast
lemma subtuple_rtranclp_intro:
assumes "∧xm ym. R (f xm) (f ym) ==> subtuple R xm ym"
and "bij_on_trancl R f"
and "R** (f xm) (f ym)"
shows "subtuple R** xm ym"
proof -
have "(λxm ym. R (f xm) (f ym))** xm ym"
apply (insert assms(2) assms(3))
by (rule reflect_rtranclp; auto)
with assms(1) have "(subtuple R)** xm ym"
by (metis (mono_tags, lifting) mono_rtranclp)
hence "subtuple R** xm ym"
by (rule rtrancl_to_subtuple)
thus ?thesis by simp
qed
lemma strict_subtuple_rtranclp_intro:
assumes "∧xm ym. R (f xm) (f ym) ==>
strict_subtuple (λx y. R x y ∨ x = y) xm ym"
and "bij_on_trancl R f"
and "acyclicP_on (fmran' ym) R"
and "R++ (f xm) (f ym)"
shows "strict_subtuple R** xm ym"
proof -
have "(λxm ym. R (f xm) (f ym))++ xm ym"
apply (insert assms(1) assms(2) assms(4))
by (rule reflect_tranclp; auto)
hence "(strict_subtuple (λx y. R x y ∨ x = y))++ xm ym"
by (rule tranclp_trans_induct;
auto simp add: assms(1) tranclp.r_into_trancl)
with assms(3) have "strict_subtuple (λx y. R x y ∨ x = y)** xm ym"
by (rule trancl_to_strict_subtuple')
thus ?thesis by simp
qed
(*** Code Setup *************************************************************)
subsection ‹Code Setup›
abbreviation "subtuple_fun f xm ym ≡
fBall (fmdom ym) (λx. rel_option f (fmlookup xm x) (fmlookup ym x))"
abbreviation "strict_subtuple_fun f xm ym ≡
subtuple_fun f xm ym ∧ xm ≠ ym"
lemma subtuple_fun_simp [code_abbrev, simp]:
"subtuple_fun f xm ym = subtuple f xm ym"
by (simp add: fmrel_on_fset_alt_def)
lemma strict_subtuple_fun_simp [code_abbrev, simp]:
"strict_subtuple_fun f xm ym = strict_subtuple f xm ym"
by simp
end
¤ Dauer der Verarbeitung: 0.6 Sekunden
¤
*© Formatika GbR, Deutschland