theory ex_4_7
  imports Main ex_3_5
begin
fun balanced::"nat \<Rightarrow> alpha list \<Rightarrow> bool" where
"balanced 0 [] = True" |
"balanced _ [] = False" |
"balanced 0 (b # as) = False" |
"balanced (Suc n) (b # as) = balanced n as" |
"balanced n (a # as) = balanced (Suc n) as"

theorem balanced_n_S_n:"balanced n w = S (replicate n a @ w)"
proof
  show "balanced n w \<Longrightarrow> S (replicate n a @ w)"
  proof (induction n w rule:balanced.induct)
    case 1
    show ?case using S.intros(1) by simp
  next
    case 2
    hence False by simp
    thus ?case by blast
  next
    case 3
    hence False by simp
    thus ?case by blast
  next
    case (4 n as)
    hence "S (replicate n a @ as)" by simp
    moreover have "S (replicate n a @ as) \<Longrightarrow> S (replicate (Suc n) a @ b # as)"
    proof (induction "replicate n a @ as" arbitrary: n as rule:S.induct)
      case 1
      thus ?case using S.intros(1) S.intros(2) by fastforce
    next
      case (2 w)
      show ?case
      proof (cases n)
        case 0
        with "2.hyps"(3) have "a # w @ [b] = as" by simp
        with S.intros(2) `S w` have "S as" by fastforce

        from S.intros have "S (a # [b])" by fastforce
        with `S as` S.intros(3) have "S (a # [b] @ as)" by fastforce
        thus ?thesis using 0 by simp
      next
        case (Suc n_1)
        let ?as_front = "take (length as - 1) as"
        from "2.hyps"(3) Suc have "w @ [b] = replicate n_1 a @ as" by simp
        moreover hence as:"as = ?as_front @ [b]"
          by (metis (mono_tags, lifting) alpha.distinct(1) append_Nil2 butlast_conv_take empty_replicate last_appendR last_replicate snoc_eq_iff_butlast)
        ultimately have "w = replicate n_1 a @ ?as_front"
          by (metis Nil_is_append_conv butlast_append butlast_snoc)
        with "2.hyps"(2) Suc have "S (replicate n a @ b # ?as_front)" by simp
        with S.intros(2) have "S (replicate (Suc n) a @ b # ?as_front @ [b])" by fastforce
        with as show ?thesis by simp
      qed
    next
      case (3 x y)
      show ?case
      proof cases
        assume "n \<le> length x"
        with "3.hyps"(5) have x:"x = (replicate n a) @ drop n x"
          by (metis append_eq_append_conv_if append_eq_conv_conj length_replicate)
        with "3.hyps"(5) have as:"drop n x @ y = as"
          by (metis append.assoc same_append_eq)

        from "3.hyps"(2) x have "S (replicate (Suc n) a @ b # (drop n x))" by fastforce
        with S.intros(3) "3.hyps"(3) have "S (replicate (Suc n) a @ b # (drop n x) @ y)" by fastforce
        with as show ?case by simp
      next
        assume asm:"\<not> n \<le> length x"

        let ?x = "replicate (length x) a"
        from "3.hyps"(5) have "x = take (length x) (replicate n a @ as)"
          using append_eq_conv_conj by blast
        also have "... = ?x" using asm by auto
        finally have "x = ?x" .

        let ?y = "replicate (n - length x) a @ as"
        let ?y_front_a = "replicate (Suc (n - length x)) a"
        let ?y_ab = "?y_front_a @ b # as"
        from "3.hyps"(5) asm have "y = ?y"
          by (metis append_eq_append_conv_if drop_replicate length_replicate)
        with "3.hyps"(4) have "S ?y_ab" by fastforce
        with S.intros(3) "3.hyps"(1) have "S (x @ ?y_ab)" by fastforce

        have "?x @ ?y_front_a = replicate (Suc n) a" using asm
          by (metis replicate_add add_Suc_right le_add_diff_inverse nat_le_linear)
        with `x = ?x` `S (x @ ?y_ab)` show ?case by (metis append_assoc)
      qed
    qed
    ultimately show ?case by simp
  next
    case (5 n as)
    thus ?case by (simp add: replicate_app_Cons_same)
  qed
next
  have b_notS:"S (b # as) \<Longrightarrow> False" for as
  proof (induction "b # as" arbitrary: as rule:S.induct)
    case (3 x y)
    show ?case
    proof (cases x)
      case Nil
      with "3.hyps"(5) have "y = b # as" by simp
      with "3.hyps"(4) show ?thesis by blast
    next
      case Cons
      with "3.hyps"(5) have "x = b # drop 1 x" by simp
      with "3.hyps"(2) show ?thesis by blast
    qed
  qed
  have "\<not>balanced n w \<Longrightarrow> \<not> S(replicate n a @ w)"
  proof (induction n w rule:balanced.induct)
    case 1
    hence False by simp
    thus ?case by simp
  next
    case (2 n)
    have "S (replicate (Suc n) a) \<Longrightarrow> False"
    proof (induction "replicate (Suc n) a" arbitrary: n rule: S.induct)
      case 1
      thus ?case by simp
    next
      case (2 w)
      from "2.hyps"(3) show ?case
        by (metis alpha.distinct(1) last_ConsR last_replicate nat.distinct(2) snoc_eq_iff_butlast)
    next
      case (3 x y)
      show ?case
      proof (cases x)
        case Nil
        with "3.hyps"(5) have "y = replicate (Suc n) a" by simp
        with "3.hyps"(4) show ?thesis by fastforce
      next
        case Cons
        from "3.hyps"(5) have "x = replicate (length x) a"
          by (metis append_eq_append_conv length_append length_replicate replicate_add)
        moreover with Cons have "length x = Suc (length x - 1)" by simp
        ultimately show ?thesis using "3.hyps"(2) by metis
      qed
    qed
    thus ?case by auto
  next
    case (3 as)
    with b_notS show ?case by fastforce
  next
    case (4 n as)
    have "S (replicate (Suc n) a @ b # as) \<Longrightarrow> S (replicate n a @ as)"
    proof (induction "replicate (Suc n) a @ b # as" arbitrary:n as rule:S.induct)
      case 1
      hence False by simp
      thus ?case by blast
    next
      case (2 w)
      show ?case
      proof (cases n)
        case 0
        show ?thesis
        proof (cases w)
          case Nil
          with "2.hyps"(3) 0 have "as = []" by simp
          thus ?thesis using 0 S.intros(1) by simp
        next
          case Cons
          with "2.hyps"(3) 0 have "w = b # drop 1 w" by simp
          with b_notS "2.hyps"(1) have False by metis
          thus ?thesis by blast
        qed
      next
        case (Suc n_1)
        have as_notS:"S(replicate (Suc k) a) \<Longrightarrow> False" for k
        proof (induction "replicate (Suc k) a" arbitrary: k rule:S.induct)
          case 1
          thus ?case by simp
        next
          case 2
          from "2.hyps"(3) show ?case
            by (metis alpha.distinct(1) last.simps last_replicate nat.distinct(1) snoc_eq_iff_butlast)
        next
          case (3 x y)
          show ?case
          proof (cases x)
            case Nil
            with "3.hyps"(5) have "y = replicate (Suc k) a" by simp
            with "3.hyps"(4) show ?thesis by auto
          next
            case Cons
            with "3.hyps"(5) have "x = replicate (length x) a"
              by (metis append.assoc append_eq_append_conv append_replicate_commute length_replicate)
            with "3.hyps"(2) Cons show ?thesis by auto
          qed
        qed
        show ?thesis
        proof (cases as)
          case Nil
          with "2.hyps"(3) Suc have "w = replicate (Suc n_1) a" by simp
          with "2.hyps"(1) as_notS show ?thesis by blast
        next
          case Cons
          let ?as_front = "take (length as - 1) as"
          have "\<lbrakk>d @ [b] = e @ b # f; f = g @ [b]\<rbrakk> \<Longrightarrow> d = e @ b # g" for d e f g by simp
          moreover from "2.hyps"(3) have "w @ [b] = replicate n a @ b # as" by simp
          moreover with Cons have as:"as = ?as_front @ [b]"
            by (metis append_butlast_last_id butlast_conv_take last.simps last_append list.distinct(1))
          ultimately have "w = replicate n a @ b # ?as_front" by blast

          with "2.hyps"(2) Suc have "S (replicate n_1 a @ ?as_front)" by simp
          with S.intros(2) have "S (replicate (Suc n_1) a @ ?as_front @ [b])" by fastforce
          with Suc as show ?thesis by auto
        qed
      qed
    next
      case (3 x y)
      have "length x \<le> n \<or> (length x = Suc n) \<or> length x \<ge> n + 2" by auto
      thus ?case
      proof
        assume asm:"length x \<le> n"
        hence "length x \<le> Suc n" by auto
        with "3.hyps"(5) have x:"x = replicate (length x) a"
          by (metis append_eq_append_conv_if append_eq_conv_conj length_replicate nat_le_iff_add replicate_add)
        with "3.hyps"(5) `length x \<le> Suc n` have "y = replicate (Suc n - length x) a @ b # as"
          by (metis append_eq_append_conv_if drop_replicate length_replicate)
        moreover from asm have "Suc n - length x > 0" by auto
        ultimately have "S (replicate (n - length x) a @ as)" using "3.hyps"(4)
          by (simp add: Suc_diff_le)
        with S.intros(3) "3.hyps"(1) x have "S (replicate (length x) a @ replicate (n - length x) a @ as)" by auto
        with asm show ?case by (metis replicate_add append_assoc le_add_diff_inverse)
      next
        assume "length x = Suc n \<or> length x \<ge> n + 2"
        thus ?case
        proof
          assume "length x = Suc n"
          with "3.hyps"(5) have "y = b # as"
            by (metis append_eq_append_conv length_replicate)
          with b_notS "3.hyps"(3) have False by auto
          thus ?case by auto
        next
          assume asm:"length x \<ge> n + 2"
          let ?front = "(replicate (Suc n) a @ [b])"
          let ?x_excess = "(length x - length ?front)"
          from "3.hyps"(5) have "x @ y = ?front @ as" by simp
          moreover from asm have "length x \<ge> length ?front" by auto
          ultimately have "x = ?front @ take ?x_excess as"
            by (metis append.right_neutral cancel_comm_monoid_add_class.diff_cancel dual_order.refl take_0 take_all take_append)
          with "3.hyps"(2) have "S (replicate n a @ take ?x_excess as)" by simp
          moreover from `x @ y = ?front @ as` `length x \<ge> length ?front` have "y = drop ?x_excess as"
            by (metis append_eq_conv_conj drop_append drop_eq_Nil self_append_conv2)
          ultimately show ?case using "3.hyps"(3) S.intros(3) by fastforce
        qed
      qed
    qed
    hence "\<not> S (replicate n a @ as) \<Longrightarrow> \<not> S (replicate (Suc n) a @ b # as)" by blast
    with "4.prems" "4.IH" show ?case by fastforce
  next
    case 5
    thus ?case
      by (metis Cons_eq_appendI balanced.simps(5) replicate_Suc replicate_app_Cons_same)
  qed
  thus "S (replicate n a @ w) \<Longrightarrow> balanced n w" by blast
qed

lemma balanced_S:"S w = balanced 0 w"
  by (simp add: balanced_n_S_n)

lemma "S [a, a, b, a, b, b]"
  by (simp add: balanced_S)
end


(* Property from Case-Analysis for Rippling and Inductive Proof,
   Moa Johansson, Lucas Dixon and Alan Bundy, ITP 2010.
   This Isabelle theory is produced using the TIP tool offered at the following website:
     https://github.com/tip-org/tools
   This file was originally provided as part of TIP benchmark at the following website:
     https://github.com/tip-org/benchmarks
   Yutaka Nagashima at CIIRC, CTU changed the TIP output theory file slightly
   to make it compatible with Isabelle2017.*)
  theory TIP_prop_59
imports "../../Test_Base"
begin

datatype 'a list = nil2 | cons2 "'a" "'a list"

datatype Nat = Z | S "Nat"

fun x :: "'a list => 'a list => 'a list" where
"x (nil2) z = z"
| "x (cons2 z2 xs) z = cons2 z2 (x xs z)"

fun last :: "Nat list => Nat" where
"last (nil2) = Z"
| "last (cons2 z (nil2)) = z"
| "last (cons2 z (cons2 x2 x3)) = last (cons2 x2 x3)"

theorem property0 :
  "((ys = (nil2)) ==> ((last (x xs ys)) = (last xs)))"
  oops

end


(*<*)
(*
   Title:  Theory  DataDependencies.thy
   Author: Maria Spichkova <maria.spichkova at rmit.edu.au>, 2014
*)
(*>*)

header "Inter-/Intracomponent dependencies"

theory DataDependencies
  imports DataDependenciesConcreteValues
begin

--"component and its subcomponents should be defined on different abstraction levels"
definition
correctCompositionDiffLevels :: "CSet \<Rightarrow> bool"
where
  "correctCompositionDiffLevels S \<equiv>
   \<forall> C \<in>  subcomp S. \<forall> i. S \<in> AbstrLevel i \<longrightarrow> C \<notin> AbstrLevel i"

--"General system's property: for all abstraction levels and all components should hold"
--"component and its subcomponents should be defined on different abstraction levels"
definition
correctCompositionDiffLevelsSYSTEM :: "bool"
where
  "correctCompositionDiffLevelsSYSTEM \<equiv>
   (\<forall> S::CSet. (correctCompositionDiffLevels S))"

--"if a local variable belongs to one of the subcomponents, it also belongs to the composed component"
definition
correctCompositionVAR ::  "CSet \<Rightarrow> bool"
where
  "correctCompositionVAR S \<equiv>
   \<forall> C \<in>  subcomp S. \<forall> v \<in> VAR C.  v \<in> VAR S"

--"General system's property: for all abstraction levels and all components should hold"
--"if a local variable belongs to one of the subcomponents, it also belongs to the composed component"
definition
correctCompositionVARSYSTEM ::  "bool"
where
  "correctCompositionVARSYSTEM \<equiv>
   (\<forall> S::CSet. (correctCompositionVAR S))"

--"after correct decomposition of a component each of its local variable can belong only to one of its subcomponents"
definition
correctDeCompositionVAR ::  "CSet \<Rightarrow> bool"
where
  "correctDeCompositionVAR S \<equiv>
   \<forall> v \<in> VAR S.  \<forall> C1 \<in>  subcomp S. \<forall> C2 \<in>  subcomp S. v \<in> VAR C1 \<and> v \<in> VAR C2 \<longrightarrow> C1 = C2"

--"General system's property: for all abstraction levels and all components should hold"
--"after correct decomposition of a component each of its local variable can belong only to one of its subcomponents"
definition
correctDeCompositionVARSYSTEM ::  "bool"
where
  "correctDeCompositionVARSYSTEM \<equiv>
  (\<forall> S::CSet. (correctDeCompositionVAR S))"

--"if x is an output channel of a  component C on some anstraction level,
it cannot be an output of another component on the same level"
definition
correctCompositionOUT ::  "chanID \<Rightarrow> bool"
where
  "correctCompositionOUT x \<equiv>
   \<forall> C i. x \<in> OUT C \<and> C \<in> AbstrLevel i \<longrightarrow>  (\<forall> S \<in> AbstrLevel i. x \<notin> OUT S)"

--"General system's property: for all abstraction levels and all channels should hold"
definition
correctCompositionOUTSYSTEM ::  "bool"
where
  "correctCompositionOUTSYSTEM \<equiv> (\<forall> x. correctCompositionOUT x)"

--"if X is a subcomponent of a  component C on some anstraction level,
it cannot be a subcomponent of another component on the same level"
definition
correctCompositionSubcomp ::  "CSet \<Rightarrow> bool"
where
  "correctCompositionSubcomp X \<equiv>
   \<forall> C i. X \<in> subcomp C \<and> C \<in> AbstrLevel i \<longrightarrow>  (\<forall> S \<in> AbstrLevel i. (S \<noteq> C \<longrightarrow> X \<notin> subcomp S))"

--"General system's property: for all abstraction levels and all components should hold"
definition
correctCompositionSubcompSYSTEM ::  "bool"
where
  "correctCompositionSubcompSYSTEM \<equiv> (\<forall> X. correctCompositionSubcomp X)"

--"If a component belongs is defined in the set CSet,
it should belong to at least one abstraction level"
definition
allComponentsUsed ::  "bool"
where
  "allComponentsUsed \<equiv>  \<forall> C. \<exists> i.  C \<in> AbstrLevel i"

--"if a component does not have any local variables, none of its subcomponents has any local variables"
lemma correctDeCompositionVARempty:
  assumes "correctCompositionVAR S"
          and "VAR S = {}"
  shows    "\<forall> C \<in>  subcomp S. VAR C = {}"
using assms by (metis all_not_in_conv correctCompositionVAR_def)

--"function OUTfrom maps channel ID to the set of input channels it depends from,"
--"directly (OUTfromCh) or via local variables (VARfrom)"
--"an empty set means that the channel is either input of the system or"
--"its values are generated within some component independently"
definition OUTfrom ::  "chanID \<Rightarrow> chanID set"
where
 "OUTfrom x \<equiv> (OUTfromCh x) \<union> {y. \<exists> v. v \<in> (OUTfromV x) \<and> y \<in> (VARfrom v)}"

--"if x depends from some input channel(s) directly, then exists"
--"a component which has them as input channels and x as an output channel"
definition
  OUTfromChCorrect :: "chanID \<Rightarrow> bool"
where
  "OUTfromChCorrect x \<equiv>
   (OUTfromCh x \<noteq> {} \<longrightarrow>
      (\<exists> Z . (x \<in> (OUT Z) \<and> (\<forall> y \<in> (OUTfromCh x). y \<in> IN Z) )))"

--"General system's property: for channels in the system should hold:"
--"if x depends from some input channel(s) directly, then exists"
--"a component which has them as input channels and x as an output channel"
definition
  OUTfromChCorrectSYSTEM :: "bool"
where
  "OUTfromChCorrectSYSTEM \<equiv> (\<forall> x::chanID. (OUTfromChCorrect x))"

--"if x depends from some local variables, then exists a component"
--"to which these variables belong and which has  x as an output channel"
definition
  OUTfromVCorrect1 :: "chanID \<Rightarrow> bool"
where
  "OUTfromVCorrect1 x \<equiv>
   (OUTfromV x \<noteq> {} \<longrightarrow>
      (\<exists> Z . (x \<in> (OUT Z) \<and> (\<forall> v \<in> (OUTfromV x). v \<in> VAR Z) )))"

--"General system's property: for channels in the system should hold the above property:"
definition
  OUTfromVCorrect1SYSTEM :: "bool"
where
  "OUTfromVCorrect1SYSTEM \<equiv> (\<forall> x::chanID. (OUTfromVCorrect1 x))"

--"if x does not depend from any local variables, then it does not belong to any set VARfrom"
definition
  OUTfromVCorrect2 :: "chanID \<Rightarrow> bool"
where
  "OUTfromVCorrect2 x \<equiv>
   (OUTfromV x = {} \<longrightarrow> (\<forall> v::varID. x \<notin> (VARto v)) )"

--"General system's property: for channels in the system should hold the above property:"
definition
  OUTfromVCorrect2SYSTEM :: "bool"
where
  "OUTfromVCorrect2SYSTEM \<equiv>  (\<forall> x::chanID. (OUTfromVCorrect2 x))"

--"General system's property:"
--"definitions OUTfromV and VARto should give equivalent mappings"
definition
  OUTfromV_VARto :: "bool"
where
  "OUTfromV_VARto \<equiv>
   (\<forall> x::chanID. \<forall> v::varID. (v \<in> OUTfromV x \<longleftrightarrow> x \<in> (VARto v)) )"

--"General system's property for abstraction levels 0 and 1"
--"if a variable v belongs to a component, then all the channels v"
--"depends from should be input channels of this component"
definition
  VARfromCorrectSYSTEM :: "bool"
where
  "VARfromCorrectSYSTEM \<equiv>
   (\<forall> v::varID. \<forall> Z\<in> ((AbstrLevel level0) \<union> (AbstrLevel level1)).
     ( (v \<in> VAR Z) \<longrightarrow>  (\<forall> x \<in> VARfrom v. x \<in> IN Z) ))"

--"General system's property for abstraction levels 0 and 1"
--"if a variable v belongs to a component, then all the channels v"
--"provides value to should be input channels of this component"
definition
  VARtoCorrectSYSTEM :: "bool"
where
  "VARtoCorrectSYSTEM \<equiv>
   (\<forall> v::varID. \<forall> Z \<in> ((AbstrLevel level0) \<union> (AbstrLevel level1)).
     ( (v \<in> VAR Z) \<longrightarrow>   (\<forall> x \<in> VARto v. x \<in> OUT Z)))"

--"to detect local variables, unused for computation of any output"
definition
  VARusefulSYSTEM :: "bool"
where
  "VARusefulSYSTEM \<equiv> (\<forall> v::varID. (VARto v \<noteq> {}))"

lemma
  OUTfromV_VARto_lemma:
 assumes "OUTfromV x \<noteq> {}"  and "OUTfromV_VARto"
 shows    "\<exists> v::varID. x \<in> (VARto v)"
 using assms by (simp add: OUTfromV_VARto_def, auto)

(*<*)
(*>*)
subsection {* Direct and indirect data dependencies between components *}

--"The component C should be defined on the same abstraction"
--"level we are seaching for its direct or indirect sources,"
--"otherwise we get an empty set as result"
definition
  DSources :: "AbstrLevelsID \<Rightarrow> CSet \<Rightarrow> CSet set"
where
 "DSources i C \<equiv> {Z.  \<exists> x. x \<in> (IN C) \<and> x \<in> (OUT Z) \<and> Z \<in> (AbstrLevel i) \<and> C \<in> (AbstrLevel i)}"

lemma DSourcesLevelX:
"(DSources i X)  \<subseteq> (AbstrLevel i)"
by (simp add: DSources_def, auto)

--"The component C should be defined on the same abstraction level we are"
--"seaching for its direct or indirect acceptors (coponents, for which C is a source),"
--"otherwise we get an empty set as result"
definition
  DAcc :: "AbstrLevelsID \<Rightarrow> CSet \<Rightarrow> CSet set"
where
 "DAcc i C \<equiv> {Z.  \<exists> x. x \<in> (OUT C) \<and> x \<in> (IN Z) \<and> Z \<in> (AbstrLevel i) \<and> C \<in> (AbstrLevel i)}"

axiomatization
  Sources :: "AbstrLevelsID \<Rightarrow> CSet \<Rightarrow> CSet set"
where
SourcesDef:
"(Sources i C) = (DSources i C) \<union> (\<Union> S \<in> (DSources i C). (Sources i S))"
and
SourceExistsDSource:
"S \<in> (Sources i C) \<longrightarrow> (\<exists> Z. S \<in> (DSources i Z))"
and
NDSourceExistsDSource:
"S \<in> (Sources i C) \<and> S \<notin> (DSources i C) \<longrightarrow>
 (\<exists> Z. S \<in> (DSources i Z) \<and> Z \<in> (Sources i C))"
and
SourcesTrans:
"(C \<in> Sources i S \<and> S \<in> Sources i Z) \<longrightarrow> C \<in> Sources i Z"
and
SourcesLevelX:
"(Sources i X)  \<subseteq> (AbstrLevel i)"
and
SourcesLoop:
"(Sources i C) = (XS \<union> (Sources i S)) \<and> (Sources i S) = (ZS \<union> (Sources i C))
\<longrightarrow> (Sources i C) = XS  \<union> ZS \<union> { C, S}"
-- "if we have a loop in the dependencies we need to cut it for counting the sources"

axiomatization
  Acc :: "AbstrLevelsID \<Rightarrow> CSet \<Rightarrow> CSet set"
where
AccDef:
"(Acc i C) = (DAcc i C) \<union> (\<Union> S \<in> (DAcc i C). (Acc i S))"
and
Acc_Sources:
"(X \<in> Acc i C) = (C \<in> Sources i X)"
and
AccSigleLoop:
"DAcc i C = {S} \<and> DAcc i S = {C} \<longrightarrow> Acc i C = {C, S}"
and
AccLoop:
"(Acc i C) = (XS \<union> (Acc i S)) \<and> (Acc i S) = (ZS \<union> (Acc i C))
\<longrightarrow> (Acc i C) = XS  \<union> ZS \<union> { C, S}"
-- "if we have a loop in the dependencies we need to cut it for counting the accessors"

lemma Acc_SourcesNOT: "(X \<notin> Acc i C) = (C \<notin> Sources i X)"
by (metis Acc_Sources)

--"component S is not a source for any component on the abstraction level i"
definition
  isNotDSource :: "AbstrLevelsID \<Rightarrow> CSet \<Rightarrow> bool"
where
 "isNotDSource i S \<equiv> (\<forall> x \<in> (OUT S). (\<forall> Z \<in> (AbstrLevel i). (x \<notin> (IN Z))))"

--"component S is not a source for a component Z on the abstraction level i"
definition
  isNotDSourceX :: "AbstrLevelsID \<Rightarrow> CSet \<Rightarrow> CSet \<Rightarrow> bool"
where
 "isNotDSourceX i S C \<equiv> (\<forall> x \<in> (OUT S). (C \<notin> (AbstrLevel i) \<or> (x \<notin> (IN C))))"

lemma isNotSource_isNotSourceX:
"isNotDSource i S = (\<forall> C. isNotDSourceX i S C)"
by (auto, (simp add: isNotDSource_def isNotDSourceX_def)+)

lemma DAcc_DSources:
"(X \<in> DAcc i C) = (C \<in> DSources i X)"
by (auto, (simp add: DAcc_def DSources_def, auto)+)

lemma DAcc_DSourcesNOT:
"(X \<notin> DAcc i C) = (C \<notin> DSources i X)"
by (auto, (simp add: DAcc_def DSources_def, auto)+)

lemma DSource_level:
  assumes "S \<in> (DSources i C)"
  shows    "C  \<in> (AbstrLevel i)"
using assms by (simp add: DSources_def, auto)

lemma SourceExistsDSource_level:
  assumes "S \<in> (Sources i C)"
  shows    "\<exists> Z  \<in> (AbstrLevel i). (S \<in> (DSources i Z))"
using assms by (metis DSource_level SourceExistsDSource)

lemma Sources_DSources:
 "(DSources i C) \<subseteq> (Sources i C)"
proof -
  have "(Sources i C) = (DSources i C) \<union> (\<Union> S \<in> (DSources i C). (Sources i S))"
    by (rule SourcesDef)
  thus ?thesis by auto
qed

lemma NoDSourceNoSource:
  assumes "S \<notin> (Sources i C)"
  shows     "S \<notin> (DSources i C)"
using assms by (metis (full_types) Sources_DSources set_rev_mp)

lemma DSourcesEmptySources:
  assumes "DSources i C = {}"
  shows    "Sources i C = {}"
proof -
  have "(Sources i C) = (DSources i C) \<union> (\<Union> S \<in> (DSources i C). (Sources i S))"
    by (rule SourcesDef)
  with assms show ?thesis by auto
qed

lemma DSource_Sources:
  assumes  "S \<in> (DSources i C)"
  shows     "(Sources i S)  \<subseteq> (Sources i C)"
proof -
 have  "(Sources i C) = (DSources i C) \<union> (\<Union> S \<in> (DSources i C). (Sources i S))"
  by (rule SourcesDef)
  with assms show ?thesis by auto
qed

lemma SourcesOnlyDSources:
  assumes "\<forall> X. (X \<in> (DSources i C) \<longrightarrow> (DSources i X) = {})"
  shows    "Sources i C = DSources i C"
proof -
 have sDef:  "(Sources i C) = (DSources i C) \<union> (\<Union> S \<in> (DSources i C). (Sources i S))"
  by (rule SourcesDef)
 from assms have  "\<forall> X. (X \<in> (DSources i C) \<longrightarrow> (Sources i X) = {})"
   by (simp add: DSourcesEmptySources)
 hence "(\<Union> S \<in> (DSources i C). (Sources i S)) = {}"  by auto
 with sDef  show ?thesis by simp
qed

lemma SourcesEmptyDSources:
 assumes "Sources i C = {}"
 shows "DSources i C = {}"
using assms  by (metis Sources_DSources bot.extremum_uniqueI)

lemma NotDSource:
 assumes "\<forall> x \<in> (OUT S). (\<forall> Z \<in> (AbstrLevel i). (x \<notin> (IN Z)))"
 shows    "\<forall> C \<in> (AbstrLevel i) . S \<notin> (DSources i C)"
using assms  by (simp add: AbstrLevel0 DSources_def)

lemma allNotDSource_NotSource:
 assumes "\<forall> C . S \<notin> (DSources i C)"
 shows    "\<forall> Z. S \<notin> (Sources i Z)"
using assms  by (metis SourceExistsDSource)

lemma NotDSource_NotSource:
 assumes "\<forall> C \<in> (AbstrLevel i). S \<notin> (DSources i C)"
 shows    "\<forall> Z \<in> (AbstrLevel i). S \<notin> (Sources i Z)"
using assms by (metis SourceExistsDSource_level)

lemma isNotSource_Sources:
 assumes "isNotDSource i S"
 shows "\<forall> C  \<in> (AbstrLevel i). S \<notin> (Sources i C)"
using assms
by (simp add: isNotDSource_def, metis (full_types) NotDSource NotDSource_NotSource)

lemma SourcesAbstrLevel:
assumes "x \<in> Sources i S"
shows "x \<in> AbstrLevel i"
using assms
by (metis SourcesLevelX in_mono)

lemma DSourceIsSource:
  assumes  "C \<in> DSources i S"
     shows  "C \<in> Sources i S"
proof -
  have "(Sources i S) = (DSources i S) \<union> (\<Union> Z \<in> (DSources i S). (Sources i Z))"
    by (rule SourcesDef)
  with assms show ?thesis  by simp
qed

lemma DSourceOfDSource:
  assumes  "Z \<in> DSources i S"
         and  "S \<in> DSources i C"
  shows     "Z \<in> Sources i C"
using assms
proof -
  from assms have src:"Sources i S \<subseteq> Sources i C" by (simp add: DSource_Sources)
  from assms have  "Z \<in> Sources i S"  by (simp add: DSourceIsSource)
  with src   show ?thesis  by auto
qed

lemma SourceOfDSource:
  assumes  "Z \<in> Sources i S"
         and  "S \<in> DSources i C"
  shows     "Z \<in> Sources i C"
using assms
proof -
  from assms have "Sources i S \<subseteq> Sources i C" by (simp add: DSource_Sources)
  thus ?thesis by (metis (full_types) assms(1) set_rev_mp)
qed

lemma DSourceOfSource:
  assumes  cDS:"C \<in> DSources i S"
         and  sS:"S \<in> Sources i Z"
  shows     "C \<in> Sources i Z"
proof -
  from cDS have  "C \<in> Sources i S"  by (simp add: DSourceIsSource)
  from this and sS show ?thesis by (metis (full_types) SourcesTrans)
qed

lemma Sources_singleDSource:
  assumes "DSources i S = {C}"
  shows    "Sources i S = {C} \<union> Sources i C"
proof -
 have sDef:  "(Sources i S) = (DSources i S) \<union> (\<Union> Z \<in> (DSources i S). (Sources i Z))"
     by (rule SourcesDef)
  from assms have "(\<Union> Z \<in> (DSources i S). (Sources i Z)) = Sources i C"
     by auto
  with sDef assms show ?thesis by simp
qed

lemma Sources_2DSources:
  assumes "DSources i S = {C1, C2}"
  shows    "Sources i S = {C1, C2} \<union> Sources i C1  \<union> Sources i C2"
proof -
  have sDef:  "(Sources i S) = (DSources i S) \<union> (\<Union> Z \<in> (DSources i S). (Sources i Z))"
     by (rule SourcesDef)
  from assms have "(\<Union> Z \<in> (DSources i S). (Sources i Z)) = Sources i C1  \<union> Sources i C2"
     by auto
  with sDef and assms show ?thesis by simp
qed

lemma Sources_3DSources:
  assumes "DSources i S = {C1, C2, C3}"
  shows    "Sources i S = {C1, C2, C3} \<union> Sources i C1  \<union> Sources i C2  \<union> Sources i C3"
proof -
  have sDef: "(Sources i S) = (DSources i S) \<union> (\<Union> Z \<in> (DSources i S). (Sources i Z))"
     by (rule SourcesDef)
  from assms have "(\<Union> Z \<in> (DSources i S). (Sources i Z)) = Sources i C1  \<union> Sources i C2  \<union> Sources i C3"
     by auto
  with sDef and assms show ?thesis by simp
qed

lemma singleDSourceEmpty4isNotDSource:
  assumes "DAcc i C = {S}"
         and "Z \<noteq> S"
  shows "C \<notin> (DSources i Z)"
proof -
  from assms have "(Z \<notin> DAcc i C)"  by simp
  thus ?thesis by (simp add: DAcc_DSourcesNOT)
qed

lemma singleDSourceEmpty4isNotDSourceLevel:
  assumes "DAcc i C = {S}"
  shows "\<forall> Z \<in> (AbstrLevel i). Z \<noteq> S \<longrightarrow> C \<notin> (DSources i Z)"
using assms  by (metis singleDSourceEmpty4isNotDSource)

lemma "isNotDSource_EmptyDAcc":
  assumes "isNotDSource i S"
  shows    "DAcc i S ={}"
using assms  by (simp add: DAcc_def isNotDSource_def, auto)

lemma "isNotDSource_EmptyAcc":
  assumes "isNotDSource i S"
  shows    "Acc i S = {}"
proof -
  have "(Acc i S) = (DAcc i S) \<union> (\<Union> X \<in> (DAcc i S). (Acc i X))"
     by (rule AccDef)
  thus ?thesis by (metis SUP_empty Un_absorb assms isNotDSource_EmptyDAcc)
qed

lemma singleDSourceEmpty_Acc:
  assumes "DAcc i C = {S}"
         and "isNotDSource i S"
  shows  "Acc i C = {S}"
proof -
  have AccC:"(Acc i C) = (DAcc i C) \<union> (\<Union> S \<in> (DAcc i C). (Acc i S))"
     by (rule AccDef)
  from assms have "Acc i S = {}" by (simp add: isNotDSource_EmptyAcc)
  with AccC show ?thesis
     by (metis SUP_empty UN_insert Un_commute Un_empty_left assms(1))
qed

lemma singleDSourceEmpty4isNotSource:
  assumes "DAcc i C = {S}"
         and nSourcS:"isNotDSource i S"
         and "Z \<noteq> S"
  shows "C \<notin> (Sources i Z)"
proof -
  from assms have  "Acc i C = {S}"  by (simp add: singleDSourceEmpty_Acc)
  with assms have "Z \<notin> Acc i C" by simp
  thus ?thesis by (simp add: Acc_SourcesNOT)
qed

lemma singleDSourceEmpty4isNotSourceLevel:
  assumes "DAcc i C = {S}"
         and nSourcS:"isNotDSource i S"
  shows "\<forall> Z \<in> (AbstrLevel i). Z \<noteq> S \<longrightarrow> C \<notin> (Sources i Z)"
using assms
by (metis singleDSourceEmpty4isNotSource)

lemma singleDSourceLoop:
  assumes "DAcc i C = {S}"
         and "DAcc i S = {C}"
  shows "\<forall> Z \<in> (AbstrLevel i). (Z \<noteq> S \<and> Z \<noteq> C \<longrightarrow> C \<notin> (Sources i Z))"
using assms
by (metis AccSigleLoop Acc_SourcesNOT empty_iff insert_iff)

(*<*)
(*>*)
subsection {* Components that are elementary wrt. data dependencies *}

--"two output channels of a component C are corelated, if they mutually depend on the same local variable(s)"
definition
   outPairCorelated :: "CSet \<Rightarrow> chanID \<Rightarrow> chanID \<Rightarrow> bool"
where
  "outPairCorelated C x y \<equiv>
  (x \<in> OUT C) \<and>   (y \<in> OUT C) \<and>
  (OUTfromV x) \<inter> (OUTfromV y) \<noteq> {}"

--"We call a set of output channels of a conponent correlated to it output channel x,"
--"if they mutually depend on the same local variable(s)"
definition
   outSetCorelated :: "chanID \<Rightarrow> chanID set"
where
  "outSetCorelated x  \<equiv>
  { y::chanID . \<exists> v::varID. (v \<in> (OUTfromV x) \<and> (y \<in> VARto v)) }"

--"Elementary component according to the data dependencies."
--"This constraint should hold for all components on the abstraction level 1"
definition
elementaryCompDD :: "CSet \<Rightarrow> bool"
where
  "elementaryCompDD C \<equiv>
  ((\<exists> x. (OUT C) = {x} ) \<or>
   (\<forall> x \<in> (OUT C). \<forall> y \<in> (OUT C). ((outSetCorelated x) \<inter> (outSetCorelated y) \<noteq> {}) ))"

--"the set (outSetCorelated x) is empty if x does not depend from any variable"
lemma outSetCorelatedEmpty1:
 assumes "OUTfromV x = {}"
 shows "outSetCorelated x = {}"
using assms by (simp add: outSetCorelated_def)

--"if x depends from at least one variable and the predicates OUTfromV and VARto are defined correctly,"
--"the set (outSetCorelated x) contains x itself"
lemma outSetCorelatedNonemptyX:
 assumes "OUTfromV x  \<noteq> {}" and correct3:"OUTfromV_VARto"
 shows "x \<in> outSetCorelated x"
proof -
  from assms have "\<exists> v::varID. x \<in> (VARto v)"
    by (rule OUTfromV_VARto_lemma)
  from this and assms show ?thesis
    by (simp add:  outSetCorelated_def OUTfromV_VARto_def)
qed

--"if the set (outSetCorelated x) is empty, this means that x does not depend from any variable"
lemma outSetCorelatedEmpty2:
 assumes "outSetCorelated x = {}"   and correct3:"OUTfromV_VARto"
 shows  "OUTfromV x = {}"
proof (rule ccontr)
  assume OUTfromVNonempty:"OUTfromV x \<noteq> {}"
  from this and correct3 have "x \<in> outSetCorelated x"
    by (rule outSetCorelatedNonemptyX)
  from this and assms show False by simp
qed

(*<*)
(*>*)
subsection {* Set of components needed to check a specific property *}

--"set of components specified on abstreaction level i, which input channels belong to the set chSet"
definition
  inSetOfComponents :: "AbstrLevelsID \<Rightarrow> chanID set \<Rightarrow> CSet set"
where
 "inSetOfComponents i chSet \<equiv>
  {X. (((IN X) \<inter> chSet \<noteq> {})  \<and> X \<in> (AbstrLevel i))}"

--"Set of components from the abstraction level i, which output channels belong to the set chSet"
definition
  outSetOfComponents :: "AbstrLevelsID \<Rightarrow> chanID set \<Rightarrow> CSet set"
where
 "outSetOfComponents i chSet \<equiv>
  {Y. (((OUT Y) \<inter> chSet \<noteq> {}) \<and> Y \<in> (AbstrLevel i))}"

--"Set of components from the abstraction level i,"
--"which have output channels from the set chSet or are sources for such components"
definition
  minSetOfComponents ::  "AbstrLevelsID \<Rightarrow> chanID set \<Rightarrow> CSet set"
where
 "minSetOfComponents i chSet \<equiv>
  (outSetOfComponents i chSet) \<union>
  (\<Union> S \<in> (outSetOfComponents i chSet). (Sources i S))"

--"Please note that a system output cannot beat the same time a local chanel."

--"channel x is a system input on an abstraction level i"
definition systemIN ::"chanID \<Rightarrow> AbstrLevelsID \<Rightarrow> bool"
where
  "systemIN x i \<equiv> (\<exists> C1 \<in> (AbstrLevel i). x \<in> (IN C1)) \<and> (\<forall> C2 \<in> (AbstrLevel i). x \<notin> (OUT C2))"

--"channel x is a system input on an abstraction level i"
definition systemOUT ::"chanID \<Rightarrow> AbstrLevelsID \<Rightarrow> bool"
where
  "systemOUT x i \<equiv> (\<forall> C1 \<in> (AbstrLevel i). x \<notin> (IN C1)) \<and> (\<exists> C2 \<in> (AbstrLevel i). x \<in> (OUT C2))"

--"channel x is a system local channel on an abstraction level i"
definition systemLOC ::"chanID \<Rightarrow> AbstrLevelsID \<Rightarrow> bool"
where
  "systemLOC x i \<equiv> (\<exists> C1 \<in> (AbstrLevel i). x \<in> (IN C1)) \<and> (\<exists> C2 \<in> (AbstrLevel i). x \<in> (OUT C2))"

lemma systemIN_noOUT:
  assumes "systemIN x i"
  shows    "\<not> systemOUT x i"
using assms by (simp add: systemIN_def systemOUT_def)

lemma systemOUT_noIN:
  assumes "systemOUT x i"
  shows    "\<not> systemIN x i"
using assms by (simp add: systemIN_def systemOUT_def)

lemma systemIN_noLOC:
  assumes "systemIN x i"
  shows    "\<not> systemLOC x i"
using assms by (simp add: systemIN_def systemLOC_def)

lemma systemLOC_noIN:
  assumes "systemLOC x i"
  shows    "\<not> systemIN x i"
using assms by (simp add: systemIN_def systemLOC_def)

lemma systemOUT_noLOC:
  assumes "systemOUT x i"
  shows    "\<not> systemLOC x i"
using assms by (simp add: systemOUT_def systemLOC_def)

lemma systemLOC_noOUT:
  assumes "systemLOC x i"
  shows    "\<not> systemOUT x i"
using assms by (simp add: systemLOC_def systemOUT_def)

definition
  noIrrelevantChannels ::  "AbstrLevelsID \<Rightarrow> chanID set \<Rightarrow> bool"
where
 "noIrrelevantChannels i chSet \<equiv>
  \<forall> x \<in> chSet. ((systemIN x i) \<longrightarrow>
   (\<exists> Z \<in> (minSetOfComponents i chSet). x \<in> (IN Z)))"

definition
  allNeededINChannels ::  "AbstrLevelsID \<Rightarrow> chanID set \<Rightarrow> bool"
where
 "allNeededINChannels i chSet \<equiv>
  (\<forall> Z \<in> (minSetOfComponents i chSet). \<exists> x \<in> (IN Z). ((systemIN x i) \<longrightarrow> (x \<in> chSet)))"

--"the set (outSetOfComponents i chSet) should be a subset of all components specified on the abstraction level i"
lemma outSetOfComponentsLimit:
"outSetOfComponents i chSet \<subseteq> AbstrLevel i"
by (metis (lifting) mem_Collect_eq outSetOfComponents_def subsetI)

--"the set (inSetOfComponents i chSet) should be a subset of all components specified on the abstraction level i"
lemma inSetOfComponentsLimit:
"inSetOfComponents i chSet \<subseteq> AbstrLevel i"
by (metis (lifting) inSetOfComponents_def mem_Collect_eq subsetI)

--"the set of components, which are sources for the components"
--"out of (inSetOfComponents i chSet), should be a subset of"
--"all components specified on the abstraction level i"
lemma SourcesLevelLimit:
"(\<Union> S \<in> (outSetOfComponents i chSet). (Sources i S)) \<subseteq> AbstrLevel i"
proof -
  have sg1:"outSetOfComponents i chSet \<subseteq> AbstrLevel i"
    by (simp add: outSetOfComponentsLimit)
  have "\<forall> S. S \<in> (outSetOfComponents i chSet) \<longrightarrow> Sources i S \<subseteq> AbstrLevel i"
    by (metis SourcesLevelX)
  from this and sg1 show ?thesis by auto
qed

lemma minSetOfComponentsLimit:
"minSetOfComponents i chSet \<subseteq> AbstrLevel i"
proof -
  have sg1: "outSetOfComponents i chSet \<subseteq> AbstrLevel i"
    by (simp add: outSetOfComponentsLimit)
  have "(\<Union> S \<in> (outSetOfComponents i chSet). (Sources i S)) \<subseteq> AbstrLevel i"
    by (simp add:  SourcesLevelLimit)
  with sg1 show ?thesis  by (simp add: minSetOfComponents_def)
qed

(*<*)
(*>*)
subsection {* Additional properties: Remote Computation *}

--"The value of  $UplSizeHighLoad$ $x$ is True if its $UplSize$ measure is greather that a predifined value"
definition UplSizeHighLoadCh ::  "chanID \<Rightarrow> bool"
where
   "UplSizeHighLoadCh x \<equiv> (x \<in> UplSizeHighLoad)"

--"if the $Perf$ measure of at least one subcomponent is greather than a predifined value,"
--"the $Perf$ measure of this component is greather than $HighPerf$ too"
axiomatization HighPerfComp ::  "CSet \<Rightarrow> bool"
where
HighPerfComDef:
   "HighPerfComp C =
   ((C \<in> HighPerfSet) \<or> (\<exists> Z \<in> subcomp C. (HighPerfComp Z)))"

end