(*  Title:      NatInt.thy
    Author:     Sven Linker, University of Liverpool

Intervals based on natural numbers. Defines a
bottom element (empty set), infimum (set intersection),
partial order (subset relation), cardinality (set cardinality).

The union of intervals i and j can only be created, if they are consecutive, i.e.,
max i +1 = min j (or vice versa). To express consecutiveness, we employ the
predicate consec.

Also contains a "chopping" predicate N_Chop(i,j,k): i can be divided into
consecutive intervals j and k.
*)

section \<open>Discrete Intervals based on Natural Numbers\<close>

text\<open>We define a type of intervals based on the natural numbers. To that
end, we employ standard operators of Isabelle, but in addition prove some
structural properties of the intervals. In particular, we show that this type
constitutes a meet-semilattice with a bottom element and equality.

Furthermore, we show that this semilattice allows for a constrained join, i.e.,
the union of two intervals is defined, if either one of them is empty, or they are
consecutive. Finally, we define the notion of \emph{chopping} an interval into
two consecutive subintervals.\<close>

theory NatInt
  imports Main
begin

text \<open>A discrete interval is a set of consecutive natural numbers, or the empty
set.\<close>

(*
typedef nat_int = "{S . (\<exists> (m::nat) n . {m..n }=S) }"
  by auto
*)

typedef nat_int = "{(S:: nat set) . finite S }"
  by auto

print_theorems

setup_lifting type_definition_nat_int
print_theorems

subsection \<open>Basic properties of discrete intervals.\<close>

locale nat_int
interpretation nat_int_class?: nat_int .

context nat_int
begin

(*lemma un_consec_seq: "(m::nat)\<le> n \<and> n+1 \<le> l \<longrightarrow> {m..n} \<union> {n+1..l} = {m..l}"
  by auto

lemma int_conseq_seq: " {(m::nat)..n} \<inter> {n+1..l} = {}"
  by auto

lemma empty_type: "{} \<in> { S . \<exists> (m:: nat) n . {m..n}=S}"
  by auto

lemma inter_result: "\<forall>x \<in> {S . (\<exists> (m::nat) n .  {m..n }=S) }.
         \<forall>y \<in> {S . (\<exists> (m::nat) n . {m..n }=S) }.
           x \<inter> y \<in>{S . (\<exists> (m::nat) n .  {m..n }=S)}"
  using Int_atLeastAtMost by blast

lemma union_result: "\<forall>x \<in> {S . (\<exists> (m::nat) n .  {m..n }=S) }.
         \<forall>y \<in> {S . (\<exists> (m::nat) n .  {m..n }=S)  }.
           x \<noteq> {} \<and> y \<noteq> {} \<and> Max x +1 = Min y
            \<longrightarrow> x \<union> y \<in>{S . (\<exists> (m::nat) n . {m..n }=S)  }"
proof (rule ballI)+
  fix x y
  assume "x\<in> {S . (\<exists> (m::nat) n .  {m..n }=S) }"
    and "y\<in> {S . (\<exists> (m::nat) n .  {m..n }=S) }"
  then have x_def:"(\<exists>m n.  {m..n} = x) "
    and y_def:"(\<exists>m n.  {m..n} = y) " by blast+
  show   " x \<noteq> {} \<and> y \<noteq> {} \<and>   Max x+1 = Min y
            \<longrightarrow> x \<union>  y \<in> {S. (\<exists>m n.  {m..n} = S) }"
  proof
    assume pre:"x \<noteq> {} \<and> y \<noteq> {} \<and> Max x + 1 = Min y"
    then have x_int:"\<exists>m n. m \<le> n \<and> {m..n} = x"
          and y_int:"(\<exists>m n. m \<le> n \<and> {m..n} = y)"
      using  x_def y_def by force+
    {
      fix ya yb xa xb
      assume y_prop:"ya \<le> yb \<and> {ya..yb} = y"
      assume x_prop:"xa \<le> xb \<and> {xa..xb} = x"
      from  x_prop have upper_x:"Max x = xb"
        by (metis Sup_nat_def cSup_atLeastAtMost)
      from y_prop have lower_y:"Min y = ya"
        by (metis Inf_fin.coboundedI Inf_fin_Min Min_in add.right_neutral finite_atLeastAtMost
            le_add1 ord_class.atLeastAtMost_iff order_class.antisym pre)
      from upper_x and lower_y and pre have upper_eq_lower: "xb+1 = ya"
        by blast
      hence "y= {xb+1 .. yb}" using y_prop by blast
      hence "x \<union> y = {xa..yb}"
        using un_consec_seq upper_eq_lower x_prop y_prop by blast
      then have " x \<union> y \<in> {S.(\<exists>m n.  {m..n} = S) }"
        by auto
    }
    then show "x \<union> y \<in> {S.(\<exists>m n.  {m..n} = S)}"
      using x_int y_int by blast
  qed
qed

lemma union_empty_result1: "\<forall>i \<in> {S . (\<exists> (m::nat) n .  {m..n }=S) }.
                                  i \<union> {} \<in> {S . (\<exists> (m::nat) n .  {m..n }=S) }"
  by blast

lemma union_empty_result2: "\<forall>i \<in> {S . (\<exists> (m::nat) n . {m..n }=S)  }.
                                  {} \<union> i \<in> {S . (\<exists> (m::nat) n . {m..n }=S)  }"
  by blast

lemma finite:" \<forall>i \<in> {S . (\<exists> (m::nat) n .  {m..n }=S) } . (finite i)"
  by blast

lemma not_empty_means_seq:"\<forall>i \<in> {S . (\<exists> (m::nat) n .  {m..n }=S) } . i \<noteq> {}
                            \<longrightarrow> ( \<exists>m n . m \<le> n \<and> {m..n} = i)"
  using atLeastatMost_empty_iff
  by force
*)
end

text \<open>The empty set is the bottom element of the type. The infimum/meet of
the semilattice is set intersection. The order is given by the subset relation.
\<close>

instantiation nat_int:: bounded_lattice_bot
begin
lift_definition bot_nat_int :: "nat_int" is Set.empty by force
lift_definition inf_nat_int  ::"nat_int \<Rightarrow> nat_int \<Rightarrow> nat_int" is Set.inter  by force
lift_definition sup_nat_int  ::"nat_int \<Rightarrow> nat_int \<Rightarrow> nat_int" is Set.union  by force
lift_definition less_eq_nat_int :: "nat_int \<Rightarrow> nat_int \<Rightarrow> bool" is Set.subset_eq .
lift_definition less_nat_int :: "nat_int \<Rightarrow> nat_int \<Rightarrow> bool" is Set.subset .
instance
proof
  fix i j k ::nat_int
  show "(i < j) = (i \<le> j \<and> \<not> j \<le> i)"
    by (simp add: less_eq_nat_int.rep_eq less_le_not_le less_nat_int.rep_eq)
  show "i \<le> i" by (simp add:less_eq_nat_int.rep_eq)
  show " i \<le> j \<Longrightarrow> j \<le> k \<Longrightarrow> i \<le> k" by (simp add:less_eq_nat_int.rep_eq)
  show "i \<le> j \<Longrightarrow> j \<le> i \<Longrightarrow> i = j"
    by (simp add: Rep_nat_int_inject less_eq_nat_int.rep_eq )
  show "bot \<le> i" using  less_eq_nat_int.rep_eq
    using bot_nat_int.rep_eq by blast
  show "i \<le> j \<Longrightarrow> i \<le> k \<Longrightarrow> i \<le> inf j k"
    by (simp add: inf_nat_int.rep_eq less_eq_nat_int.rep_eq)
  show " inf i   j \<le> i"
    by (simp add: inf_nat_int.rep_eq less_eq_nat_int.rep_eq)
  show "inf i  j \<le> j"
    by (simp add: inf_nat_int.rep_eq less_eq_nat_int.rep_eq)
  show "i \<le> sup i j"
    by (simp add: sup_nat_int.rep_eq less_eq_nat_int.rep_eq)
  show "j \<le> sup i j"
    by (simp add: sup_nat_int.rep_eq less_eq_nat_int.rep_eq)
  show "j \<le> i \<Longrightarrow> k \<le> i \<Longrightarrow> sup j k \<le> i"
    by (simp add: sup_nat_int.rep_eq less_eq_nat_int.rep_eq)
qed
end

(*instantiation nat_int :: bot
begin
lift_definition bot_nat_int :: "nat_int" is Set.empty by force
instance by standard
end

instantiation nat_int ::  inf
begin
lift_definition inf_nat_int  ::"nat_int \<Rightarrow> nat_int \<Rightarrow> nat_int" is Set.inter  by force
instance
proof qed
end

instantiation nat_int :: "order_bot"
begin
lift_definition less_eq_nat_int :: "nat_int \<Rightarrow> nat_int \<Rightarrow> bool" is Set.subset_eq .
lift_definition less_nat_int :: "nat_int \<Rightarrow> nat_int \<Rightarrow> bool" is Set.subset .
instance
proof
  fix i j k ::nat_int
  show "(i < j) = (i \<le> j \<and> \<not> j \<le> i)"
    by (simp add: less_eq_nat_int.rep_eq less_le_not_le less_nat_int.rep_eq)
  show "i \<le> i" by (simp add:less_eq_nat_int.rep_eq)
  show " i \<le> j \<Longrightarrow> j \<le> k \<Longrightarrow> i \<le> k" by (simp add:less_eq_nat_int.rep_eq)
  show "i \<le> j \<Longrightarrow> j \<le> i \<Longrightarrow> i = j"
    by (simp add: Rep_nat_int_inject less_eq_nat_int.rep_eq )
  show "bot \<le> i" using  less_eq_nat_int.rep_eq
    using bot_nat_int.rep_eq by blast
qed
end

instantiation nat_int ::  "semilattice_inf"
begin
instance
proof
  fix i j k :: nat_int
  show "i \<le> j \<Longrightarrow> i \<le> k \<Longrightarrow> i \<le> inf j k"
    by (simp add: inf_nat_int.rep_eq less_eq_nat_int.rep_eq)
  show " inf i   j \<le> i"
    by (simp add: inf_nat_int.rep_eq less_eq_nat_int.rep_eq)
  show "inf i  j \<le> j"
    by (simp add: inf_nat_int.rep_eq less_eq_nat_int.rep_eq)
qed
end
*)
instantiation nat_int:: "equal"
begin
definition equal_nat_int :: "nat_int \<Rightarrow> nat_int \<Rightarrow> bool"
  where "equal_nat_int i  j \<equiv> i \<le> j \<and> j \<le> i"
instance
proof
  fix i j :: nat_int
  show " equal_class.equal i j = (i = j)" using equal_nat_int_def  by auto
qed
end

context nat_int
begin
abbreviation subseteq :: "nat_int \<Rightarrow> nat_int\<Rightarrow> bool" (infix "\<sqsubseteq>" 30)
  where  "i \<sqsubseteq> j == i \<le> j "
abbreviation subset :: "nat_int \<Rightarrow> nat_int \<Rightarrow> bool" (infix "\<sqsubset>" 30)
  where "i \<sqsubset> j == i < j"
abbreviation empty :: "nat_int" ("\<emptyset>")
  where "\<emptyset> \<equiv> bot"

notation inf (infix "\<sqinter>" 70)
notation sup (infix "\<squnion>" 70)

(*text \<open>The union of two intervals is only defined, if it is also
a discrete interval.\<close>
definition union :: "nat_int \<Rightarrow> nat_int \<Rightarrow> nat_int" (infix "\<squnion>" 65)
  where "i \<squnion> j = Abs_nat_int (Rep_nat_int i \<union> Rep_nat_int j)"
 *)

text \<open>Non-empty intervals contain a minimal and maximal element.
Two non-empty intervals \(i\) and \(j\) are
consecutive, if the minimum of \(j\) is the successor of the
maximum of \(i\).
Furthermore, the interval \(i\) can be chopped into the intervals \(j\)
and \(k\), if the union of \(j\) and \(k\) equals \(i\), and if \(j\)
and \(k\) are not-empty, they must be consecutive. Finally, we define
the cardinality of discrete intervals by lifting the cardinality of
sets.
\<close>
lift_definition maximum :: "nat_int \<Rightarrow> nat" is Lattices_Big.linorder_class.Max  .
lift_definition minimum :: "nat_int \<Rightarrow> nat" is Lattices_Big.linorder_class.Min  .

(*definition maximum :: "nat_int \<Rightarrow> nat"
  where maximum_def: "i \<noteq> \<emptyset> \<Longrightarrow> maximum (i) =   Max (Rep_nat_int i)"
*)
(*
definition minimum :: "nat_int \<Rightarrow> nat"
  where minimum_def: "i \<noteq> \<emptyset> \<Longrightarrow> minimum(i) = Min (Rep_nat_int i)"
*)

definition consec:: "nat_int\<Rightarrow>nat_int \<Rightarrow> bool"
  where "consec i j \<equiv> (i\<noteq>\<emptyset> \<and> j \<noteq> \<emptyset> \<and> (maximum(i)+1 = minimum j))"

lift_definition card' ::"nat_int \<Rightarrow> nat"  ( "|_|" 70) is card .

text\<open>For convenience, we also lift the membership relation and its negation
to discrete intervals.\<close>

lift_definition el::"nat \<Rightarrow> nat_int \<Rightarrow> bool" (infix "\<^bold>\<in>" 50) is "Set.member" .

lift_definition not_in ::"nat \<Rightarrow> nat_int \<Rightarrow> bool" (infix "\<^bold>\<notin>" 40)  is Set.not_member .

definition continuous :: "nat_int \<Rightarrow> bool"
  where "continuous i == \<forall>n m.(n \<^bold>\<in> i \<and> m \<^bold>\<in> i \<longrightarrow> ( \<forall>l. n < l \<and> l < m \<longrightarrow> l \<^bold>\<in> i))"

definition N_Chop :: "nat_int \<Rightarrow> nat_int \<Rightarrow> nat_int \<Rightarrow> bool" ("N'_Chop'(_,_,_')" 51)
  where nchop_def :
    "N_Chop(i,j,k) \<equiv> (continuous j \<and> continuous k \<and> i =  j \<squnion> k   \<and> (j = \<emptyset> \<or>  k = \<emptyset> \<or> consec j k))"

end

lemmas[simp] = nat_int.el.rep_eq nat_int.not_in.rep_eq nat_int.card'.rep_eq

context nat_int
begin

lemma in_not_in_iff1 :"n \<^bold>\<in> i \<longleftrightarrow> \<not> n\<^bold>\<notin> i" by simp
lemma in_not_in_iff2: "n\<^bold>\<notin> i \<longleftrightarrow> \<not> n \<^bold>\<in> i" by simp

lemma in_eq:"(\<forall>l. l \<^bold>\<in> i \<longleftrightarrow> l \<^bold>\<in> j) \<longleftrightarrow> i = j"
proof
  assume "i = j"
  then show "\<forall>l. l \<^bold>\<in> i \<longleftrightarrow> l \<^bold>\<in> j"
    by simp
next
  assume  "\<forall>l. l \<^bold>\<in> i \<longleftrightarrow> l \<^bold>\<in> j"
  then show "i=j" using nat_int.el.rep_eq Rep_nat_int set_eq_iff  Rep_nat_int_inject
    by (simp add: \<open>\<And>B A. (A = B) = (\<forall>x. (x \<in> A) = (x \<in> B))\<close>)
qed

(*lemma rep_non_empty_means_seq:"continuous i
                                \<longrightarrow> (\<exists>m n. m \<le> n \<and> (Abs_nat_int {m..n} =( i)))"

  by (metis Rep_nat_int Rep_nat_int_inject bot_nat_int.rep_eq nat_int.not_empty_means_seq)*)

lemma non_empty_max: "i \<noteq> \<emptyset> \<longrightarrow> (\<exists>m . maximum(i) = m)"
  by auto

lemma non_empty_min: "i \<noteq> \<emptyset> \<longrightarrow> (\<exists>m . minimum(i) = m)"
  by auto

lemma minimum_in: "i \<noteq> \<emptyset> \<longrightarrow> minimum i \<^bold>\<in> i"
  by (metis Min_in Rep_nat_int Rep_nat_int_inject bot_nat_int.rep_eq el.rep_eq mem_Collect_eq minimum.rep_eq)
(*  by (metis Min_in atLeastatMost_empty_iff2 finite_atLeastAtMost minimum_def
      el.rep_eq rep_non_empty_means_seq)*)

lemma maximum_in: "i \<noteq> \<emptyset> \<longrightarrow> maximum i \<^bold>\<in> i"
  by (metis Max_in Rep_nat_int Rep_nat_int_inject bot_nat_int.rep_eq el.rep_eq mem_Collect_eq maximum.rep_eq)
(*  by (metis Max_in Rep_nat_int Rep_nat_int_inject bot_nat_int.rep_eq el.rep_eq local.finite maximum.rep_eq)*)
(*  by (metis Max_in atLeastatMost_empty_iff2 finite_atLeastAtMost maximum_def
      el.rep_eq rep_non_empty_means_seq)
*)
lemma non_empty_elem_in:"i \<noteq> \<emptyset> \<longleftrightarrow> (\<exists>n. n \<^bold>\<in> i)"
proof
  assume assm:"i \<noteq> \<emptyset>"
  show "\<exists>n . n \<^bold>\<in> i"
    by (metis assm Rep_nat_int_inverse all_not_in_conv el.rep_eq bot_nat_int_def)
next
  assume assm:"\<exists>n. n \<^bold>\<in> i"
  show "i \<noteq> \<emptyset>"
    using Abs_nat_int_inverse assm el.rep_eq bot_nat_int_def
    using bot_nat_int.rep_eq by auto
qed

(*
lemma leq_nat_non_empty:"(m::nat) \<le> n \<longrightarrow> Abs_nat_int{m..n} \<noteq> \<emptyset>"
proof
  assume assm:"m \<le>n"
  then have non_empty:"{m..n} \<noteq> {} "
    using atLeastatMost_empty_iff by blast
  with assm have "{m..n} \<in> {S . (\<exists> (m::nat) n .  {m..n }=S)  }" by blast
  then show "Abs_nat_int {m..n} \<noteq> \<emptyset>"
    using Abs_nat_int_inject non_empty bot_nat_int_def
    by (simp add: bot_nat_int.abs_eq)
qed

lemma continuous_nonE_atLeastAtMost:"i \<noteq>\<emptyset> \<longrightarrow> (continuous i  \<longleftrightarrow> (  \<forall>l. l \<in> {minimum i..maximum i} \<longleftrightarrow> l \<^bold>\<in> i))"
  by (metis Max_ge Min_le Rep_nat_int atLeastAtMost_iff continuos_atLeastAtMost  el.rep_eq maximum.rep_eq maximum_in mem_Collect_eq minimum.rep_eq minimum_in order_trans)

lemma atLeastAtMost_rep : "\<exists>j. \<forall>l. l \<in> {m..n} \<longleftrightarrow> l \<^bold>\<in> j"
proof -
  obtain j where "j = Abs_nat_int {m..n}" by simp
  then have " \<forall>l. l \<in> {m..n} \<longleftrightarrow> l \<^bold>\<in> j"
    by (simp add: Abs_nat_int_inverse)
  then show ?thesis by blast
qed

lemma nat_int_atLeastAtMost_min:"i \<noteq> \<emptyset> \<longrightarrow> (\<forall>l. l \<in> {m..n} \<longleftrightarrow> l \<^bold>\<in> i) \<longrightarrow> minimum i = m"
  by (metis antisym atLeastAtMost_iff atLeastatMost_empty_iff continuos_atLeastAtMost continuous_nonE_atLeastAtMost equals0D  le_eq_less_or_eq  minimum_in non_empty_elem_in)

lemma nat_int_atLeastAtMost_max:"i \<noteq> \<emptyset> \<longrightarrow> (\<forall>l. l \<in> {m..n} \<longleftrightarrow> l \<^bold>\<in> i) \<longrightarrow> maximum i = n"
  by (metis antisym atLeastAtMost_iff atLeastatMost_empty_iff continuos_atLeastAtMost continuous_nonE_atLeastAtMost equals0D  le_eq_less_or_eq  minimum_in non_empty_elem_in)

lemma singleton_continuous: "(\<forall>l. l \<in> {m} \<longleftrightarrow> l \<^bold>\<in> i) \<longrightarrow> continuous i"
  by (metis continuous_def leD less_imp_le_nat singletonD)

lemma empty_continuous :"i = \<emptyset> \<longrightarrow> continuous i"
  using continuous_def non_empty_elem_in by blast

lemma nchop_cont:" N_Chop(i,j,k) \<longrightarrow> continuous i"
proof
  assume " N_Chop(i,j,k)"
  then have 1: "continuous j" and 2:"continuous k" and 3:"i = j \<squnion> k"  and "(j = \<emptyset> \<or> k = \<emptyset> \<or> consec j k)"
    using nchop_def by auto
  then consider (j_empty) "j = \<emptyset>" | (k_empty) "k = \<emptyset>" | (j_k_consec) "consec j k" by auto
  then show "continuous i"
  proof (cases)
    case j_empty
    then have "i = k" using 3
      by simp
    then show ?thesis using 2 by simp
  next
    case k_empty
    then show ?thesis using 1 3 by simp
  next
    case j_k_consec
    then have "j \<noteq> \<emptyset>" and "k \<noteq> \<emptyset>"
      by (simp add: consec_def)+
    from 1 obtain n and m where \<open>\<forall>l. l \<in> {n..m} \<longleftrightarrow> l \<^bold>\<in> j\<close>
      using "1" continuos_atLeastAtMost by blast
    from 2 obtain p and q where \<open>\<forall>l. l \<in> {p..q} \<longleftrightarrow> l \<^bold>\<in> k\<close>
      using "1" continuos_atLeastAtMost by blast
    have "m = maximum j"
      by (metis Max_ge Rep_nat_int \<open>\<forall>l. (l \<in> {n..m}) = (l \<^bold>\<in> j)\<close> \<open>j \<noteq> bot\<close> antisym atLeastAtMost_iff atLeastatMost_empty_iff2 el.rep_eq maximum.rep_eq maximum_in mem_Collect_eq order_refl)
    have "p = minimum k"
      by (metis Min_le Rep_nat_int \<open>\<forall>l. (l \<in> {p..q}) = (l \<^bold>\<in> k)\<close> \<open>k \<noteq> bot\<close> antisym atLeastAtMost_iff atLeastatMost_empty_iff2 el.rep_eq minimum.rep_eq minimum_in mem_Collect_eq order_refl)
    then have "m+1 = p" using consec_def
      using \<open>m = maximum j\<close> j_k_consec by blast
    then have "\<forall>l. l \<in> {n..q} \<longleftrightarrow> l \<^bold>\<in> (j \<squnion> k)"
      by (metis  One_nat_def Suc_leI UnE Un_iff \<open>\<forall>l. (l \<in> {n..m}) = (l \<^bold>\<in> j)\<close> \<open>\<forall>l. (l \<in> {p..q}) = (l \<^bold>\<in> k)\<close> \<open>j \<noteq> bot\<close> \<open>k \<noteq> bot\<close> \<open>m = maximum j\<close> \<open>p = minimum k\<close> add.right_neutral add_Suc_right    atLeastAtMost_iff  atLeastatMost_empty atLeastatMost_empty_iff2  emptyE le_add1  linorder_not_less local.el.rep_eq maximum_in minimum_in   sup_nat_int.rep_eq)
    then have "continuous (j \<squnion> k)"
      by (meson atLeastAtMost_iff continuous_def less_imp_le_nat order_trans)
    then show ?thesis
      by (simp add: "3")
  qed
qed

lemma subset_min:"(i \<noteq> \<emptyset>) \<and> (j \<noteq> \<emptyset>) \<and> (i \<sqsubseteq> j) \<longrightarrow> minimum i \<ge> minimum j"
  by (metis Min_le Rep_nat_int el.rep_eq less_eq_nat_int.rep_eq local.minimum.rep_eq mem_Collect_eq minimum_in subsetCE)

lemma subset_max:"(i \<noteq> \<emptyset>) \<and> (j \<noteq> \<emptyset>) \<and> (i \<sqsubseteq> j) \<longrightarrow> maximum i \<le> maximum j"
  by (metis Max_ge Rep_nat_int el.rep_eq less_eq_nat_int.rep_eq local.maximum.rep_eq mem_Collect_eq maximum_in subsetCE)

lemma less_max: "(i \<noteq> \<emptyset>) \<and> (j \<noteq> \<emptyset>) \<and> (continuous i) \<and> (continuous j) \<and> (i \<sqsubset> j) \<and> minimum i = minimum j \<longrightarrow> maximum i < maximum j"
proof
  assume assm:"i \<noteq> \<emptyset> \<and> j \<noteq> \<emptyset> \<and> (continuous i) \<and> (continuous j) \<and> (i \<sqsubset> j) \<and> minimum i = minimum j"
  obtain m and n where 1:"\<forall>l. l \<in> {m..n} \<longleftrightarrow> l \<^bold>\<in> i"
    using assm continuos_atLeastAtMost by blast
  obtain p and q where 2:"\<forall>l. l \<in> {p..q} \<longleftrightarrow> l \<^bold>\<in> j"
    using assm continuos_atLeastAtMost by blast
  have "m = minimum i" using nat_int_atLeastAtMost_min assm 1 2 by blast
  have "p = minimum j" using nat_int_atLeastAtMost_min assm 1 2 by blast
  then have 3:"m = p"
    by (simp add: \<open>m = minimum i\<close> assm)
  have "{m..n} \<subset> {p..q}" using assm 1 2
      using less_nat_int.rep_eq by auto
  then have "n < q" using 3
      using order_trans by auto
  then show "maximum i < maximum j" using nat_int_atLeastAtMost_max assm 1 2  by simp
qed

lemma greater_min: "(i \<noteq> \<emptyset>) \<and> (j \<noteq> \<emptyset>) \<and> (continuous i) \<and> (continuous j) \<and> (i \<sqsubset> j) \<and> maximum i = maximum j \<longrightarrow> minimum i > minimum j"
proof
  assume assm:"i \<noteq> \<emptyset> \<and> j \<noteq> \<emptyset> \<and> (continuous i) \<and> (continuous j) \<and> (i \<sqsubset> j) \<and> maximum i = maximum j"
  obtain m and n where 1:"\<forall>l. l \<in> {m..n} \<longleftrightarrow> l \<^bold>\<in> i"
    using assm continuos_atLeastAtMost by blast
  obtain p and q where 2:"\<forall>l. l \<in> {p..q} \<longleftrightarrow> l \<^bold>\<in> j"
    using assm continuos_atLeastAtMost by blast
  have "n = maximum i" using nat_int_atLeastAtMost_max assm 1 2 by blast
  have "q = maximum  j" using nat_int_atLeastAtMost_max assm 1 2 by blast
  then have 3:"n = q"
    by (simp add: \<open>n = maximum i\<close> assm)
  have "{m..n} \<subset> {p..q}" using assm 1 2
      using less_nat_int.rep_eq by auto
  then have "m > p" using 3
      using order_trans by auto
  then show "minimum i > minimum j" using nat_int_atLeastAtMost_min assm 1 2  by simp
qed

(*lemma leq_min_inf':"(m::nat) \<le> n \<longrightarrow> minimum(Abs_nat_int{m..n}) = m"
proof
  assume assm:"m \<le> n"
  hence in_type:"{m..n} \<in> {S . (\<exists> (m::nat) n . m \<le> n \<and> {m..n }=S) \<or> S={} }" by blast
  from assm have "Abs_nat_int{m..n} \<noteq> \<emptyset>"  using leq_nat_non_empty by blast
  hence min:"minimum(Abs_nat_int{m..n}) = Min(Rep_nat_int (Abs_nat_int {m..n}))"
    using  minimum.rep_eq by blast
  from in_type have " (Rep_nat_int (Abs_nat_int {m..n})) = {m..n}"
    using Abs_nat_int_inverse by blast
  hence  "Min (Rep_nat_int (Abs_nat_int{m..n})) = Min {m..n}" by simp
  with min have simp_min:"minimum(Abs_nat_int{m..n}) = Min {m..n}" by simp
  from assm have "Min {m..n} = m" using leq_min_inf by blast
  with simp_min show "minimum(Abs_nat_int{m..n}) = m" by simp
qed

lemma in_refl:"(n::nat)  \<^bold>\<in> Abs_nat_int {n}"
proof -
  have "(n::nat) \<le> n" by simp
  hence "{n} \<in> {S . (\<exists> (m::nat) n . m \<le> n \<and> {m..n }=S) \<or> S={} }" by auto
  then show "n \<^bold>\<in> Abs_nat_int {n}"
    by (simp add: Abs_nat_int_inverse el_def)
qed
  *)
(*lemma in_singleton:" m \<^bold>\<in> Abs_nat_int{n} \<longrightarrow> m = n"
proof
  assume assm:" m \<^bold>\<in> Abs_nat_int{n}"
  have "(n::nat) \<le> n" by simp
  hence "{n} \<in> {S . (\<exists> (m::nat) n . m \<le> n \<and> {m..n }=S) \<or> S={} }" by auto
  with assm show "m=n" by (simp add: Abs_nat_int_inverse el_def)
qed
*)

lemma continuous_min_max: "i \<noteq> \<emptyset> \<and> j \<noteq> \<emptyset> \<and> continuous i \<and> continuous j \<and> minimum i = minimum j \<and> maximum i = maximum j \<longrightarrow> i = j"
  using continuous_nonE_atLeastAtMost in_eq by auto

subsection \<open>Algebraic properties of intersection and union.\<close>

lemma inter_empty1:"(i::nat_int) \<sqinter> \<emptyset> = \<emptyset>"
  using Rep_nat_int_inject inf_nat_int.rep_eq bot_nat_int.abs_eq bot_nat_int.rep_eq
  by fastforce

lemma inter_empty2:"\<emptyset> \<sqinter> (i::nat_int) = \<emptyset>"
  by (metis inf_commute nat_int.inter_empty1)

(*lemma un_empty_absorb1:"i \<squnion> \<emptyset> = i"
  using  Abs_nat_int_inverse Rep_nat_int_inverse sup_nat_int.rep_eq  bot_nat_int.rep_eq
  by auto

lemma un_empty_absorb2:"\<emptyset> \<squnion> i = i"
  using  Abs_nat_int_inverse Rep_nat_int_inverse union_def empty_type bot_nat_int.rep_eq
  by auto
*)
text \<open>Most properties of the union of two intervals depends on them being consecutive,
to ensure that their union exists.\<close>

(*lemma consec_un:"consec i j \<and> n \<notin> Rep_nat_int(i) \<union> Rep_nat_int j
                  \<longrightarrow> n \<^bold>\<notin>  (i \<squnion> j)"
proof
  assume assm:"consec i j \<and> n \<notin>  Rep_nat_int i \<union> Rep_nat_int j"
  thus "n \<^bold>\<notin> (i \<squnion> j)"
  proof -
    have f1: "Abs_nat_int (Rep_nat_int (i \<squnion> j))
              = Abs_nat_int (Rep_nat_int i \<union> Rep_nat_int j)"
      using Rep_nat_int_inverse union_def by presburger
    have "i \<noteq> \<emptyset> \<and> j \<noteq> \<emptyset> \<and> maximum i + 1 = minimum j"
      using assm consec_def by auto
    then have "\<exists>n na. {n..na} = Rep_nat_int i \<union> Rep_nat_int j"
      by (metis (no_types) leq_max_sup leq_min_inf maximum.rep_eq minimum_def
          rep_non_empty_means_seq un_consec_seq)
    then show ?thesis
      using f1 Abs_nat_int_inject Rep_nat_int not_in.rep_eq assm by auto
  qed
qed
*)
(*

lemma inter_distr1:"consec j k \<longrightarrow> i \<sqinter> (j \<squnion> k) = (i \<sqinter> j) \<squnion> (i \<sqinter> k)"
  unfolding consec_def
proof
  assume assm:"j \<noteq> \<emptyset> \<and> k \<noteq> \<emptyset> \<and> maximum j +1 = minimum k"
  then show " i \<sqinter> (j \<squnion> k) = (i \<sqinter> j) \<squnion> (i \<sqinter> k)"
  proof -
    have f1: "\<forall>n. n = \<emptyset> \<or> maximum n = Max (Rep_nat_int n)"
      using nat_int.maximum.rep_eq by auto
    have f2: "Rep_nat_int j \<noteq> {}"
      using assm nat_int.maximum_in by auto
    have f3: "maximum j = Max (Rep_nat_int j)"
      using f1 by (meson assm)
    have "maximum k \<^bold>\<in> k"
      using assm nat_int.maximum_in by blast
    then have "Rep_nat_int k \<noteq> {}"
      by fastforce
    then have "Rep_nat_int (j \<squnion> k) = Rep_nat_int j \<union> Rep_nat_int k"
      using f3 f2 Abs_nat_int_inverse Rep_nat_int assm nat_int.minimum_def
        sup_nat_int.rep_eq
        by auto
    then show ?thesis
      by (metis Rep_nat_int_inverse inf_nat_int.rep_eq inf_sup_distrib1 sup_nat_int.rep_eq )
  qed
qed

lemma inter_distr2:"consec j k \<longrightarrow> (j \<squnion> k) \<sqinter> i = (j \<sqinter> i) \<squnion> (k \<sqinter> i)"
  by (simp add: inter_distr1 inf_commute)

lemma un_not_elem1: "n\<^bold>\<notin> i \<squnion> j \<longrightarrow>  n \<^bold>\<notin> i"
  by (simp add: sup_nat_int.rep_eq)

lemma un_not_elem2: "n\<^bold>\<notin> i \<squnion> j \<longrightarrow>  n \<^bold>\<notin> j"
  by (simp add: sup_nat_int.rep_eq)

(*lemma consec_un_not_elem1:"consec i j \<and> n\<^bold>\<notin> i \<squnion> j \<longrightarrow>  n \<^bold>\<notin> i"
  by (simp add: sup_nat_int.rep_eq)
  using sup_nat_int.rep_eq less_eq_nat_int.rep_eq not_in.rep_eq by blast

lemma consec_un_not_elem2:"consec i j \<and> n\<^bold>\<notin> i \<squnion> j \<longrightarrow>  n \<^bold>\<notin> j"
  using  un_subset2 less_eq_nat_int.rep_eq not_in.rep_eq by blast
*)
lemma un_element1:" n \<^bold>\<in> i \<longrightarrow> n \<^bold>\<in> i \<squnion> j"
  using in_not_in_iff2 un_not_elem1 by blast

lemma un_element2:" n \<^bold>\<in> j \<longrightarrow> n \<^bold>\<in> i \<squnion> j"
  using in_not_in_iff2 un_not_elem2 by blast

lemma excl_el1: "n \<^bold>\<in> i \<and> i \<sqinter> j = \<emptyset> \<longrightarrow> n \<^bold>\<notin> j"
  by (metis Int_iff bot_nat_int.rep_eq el.rep_eq empty_iff inf_nat_int.rep_eq not_in.rep_eq)
lemma excl_el2: "n \<^bold>\<in> j \<and> i \<sqinter> j = \<emptyset> \<longrightarrow> n \<^bold>\<notin> i"
  by (metis Int_iff bot_nat_int.rep_eq el.rep_eq empty_iff inf_nat_int.rep_eq not_in.rep_eq)

lemma un_excl_el1:"n \<^bold>\<in> i \<squnion> j \<and> i \<sqinter> j = \<emptyset> \<and> n \<^bold>\<notin> i \<longrightarrow> n \<^bold>\<in> j"
  using sup_nat_int.rep_eq by auto
lemma un_excl_el2:"n \<^bold>\<in> i \<squnion> j \<and> i \<sqinter> j = \<emptyset> \<and> n \<^bold>\<notin> j \<longrightarrow> n \<^bold>\<in> i"
  using sup_nat_int.rep_eq by auto

(*lemma consec_un_element1:"consec i j \<and> n \<^bold>\<in> i \<longrightarrow> n \<^bold>\<in> i \<squnion> j"
  using less_eq_nat_int.rep_eq nat_int.el.rep_eq  by blast

lemma consec_un_element2:"consec i j \<and> n \<^bold>\<in> j \<longrightarrow> n \<^bold>\<in> i \<squnion> j"
  using less_eq_nat_int.rep_eq nat_int.el.rep_eq nat_int.un_subset2 by blast
*)

lemma ex_nat_int: "m\<le>n \<longrightarrow> (\<exists>i. \<forall>l. l\<in>{m..n} \<longleftrightarrow> l \<^bold>\<in> i)"
  using atLeastAtMost_rep by blast

lemma continuous_inter: "continuous i \<and>  continuous j \<longrightarrow> continuous (i \<sqinter> j) "
proof (cases "i \<sqinter> j = \<emptyset>")
case True
then show ?thesis
  using empty_continuous by auto
next
  case False
  then  have 1:"i \<noteq> \<emptyset>" and 2:"j \<noteq> \<emptyset>"
    by auto
  {
    assume "continuous i \<and>  continuous j"
    then obtain m and n and p and q where 3:"\<forall>l. l \<^bold>\<in> i \<longleftrightarrow> l \<in> {m..n}" and 4:"\<forall>l. l\<^bold>\<in> j \<longleftrightarrow> l \<in> {p..q}"
      by (metis continuos_atLeastAtMost)
    then have "continuous (i \<sqinter> j)"
      by (simp add: continuous_def inf_nat_int.rep_eq)
  }
  then show ?thesis by blast
qed

lemma consec_lesser:" consec i j  \<longrightarrow> (\<forall>n m. (n \<^bold>\<in> i \<and> m \<^bold>\<in> j \<longrightarrow> n < m))"
proof (rule allI|rule impI)+
  assume "consec i j"
  fix n and m
  assume assump:"n \<^bold>\<in> i \<and> m \<^bold>\<in> j "
  then have  max:"n \<le> maximum i"
    using Rep_nat_int local.maximum.rep_eq by auto
  from assump have min: "m \<ge> minimum j"
    using Rep_nat_int local.minimum.rep_eq by auto
  from min and max show less:"n < m"
    using One_nat_def Suc_le_lessD \<open>consec i j\<close> add.right_neutral add_Suc_right
      dual_order.trans leD leI consec_def by auto
qed

lemma consec_in_exclusive1:"consec i j \<and> n \<^bold>\<in> i \<longrightarrow> n \<^bold>\<notin> j"
  using nat_int.consec_lesser nat_int.in_not_in_iff2 by blast

lemma consec_in_exclusive2:"consec i j \<and> n \<^bold>\<in> j \<longrightarrow> n \<^bold>\<notin> i"
  using consec_in_exclusive1 el.rep_eq not_in.rep_eq by blast

lemma consec_un_max:"consec i j \<longrightarrow> maximum j = maximum (i \<squnion> j)"
proof
  assume assm:"consec i j"
  then have "(\<forall>n m. (n \<^bold>\<in> i \<and> m \<^bold>\<in> j \<longrightarrow> n < m))"
    using nat_int.consec_lesser by blast
  then have "\<forall>n . (n \<^bold>\<in> i \<longrightarrow> n < maximum j)"
    using assm local.consec_def nat_int.maximum_in by auto
  then have "\<forall>n. (n \<^bold>\<in> i \<squnion> j \<longrightarrow> n \<le> maximum j)"
    using Rep_nat_int local.maximum.rep_eq sup_nat_int.rep_eq by auto
  then show "maximum j = maximum (i \<squnion> j)"
    by (metis Max_ge Rep_nat_int assm bot_eq_sup_iff el.rep_eq leD le_neq_trans local.consec_def local.maximum.rep_eq maximum_in mem_Collect_eq sup_commute un_element1)
qed

lemma consec_un_min:"consec i j \<longrightarrow> minimum i = minimum (i \<squnion> j)"
proof
  assume assm:"consec i j"
  then have "(\<forall>n m. (n \<^bold>\<in> i \<and> m \<^bold>\<in> j \<longrightarrow> n < m))"
    using nat_int.consec_lesser by blast
  then have "\<forall>n . (n \<^bold>\<in> j \<longrightarrow> n > minimum i)"
    using assm local.consec_def nat_int.minimum_in by auto
  then have 1:"\<forall>n. (n \<^bold>\<in> i \<squnion> j \<longrightarrow> n \<ge> minimum i)"
    using Rep_nat_int local.minimum.rep_eq sup_nat_int.rep_eq by auto
  from assm have "i \<squnion> j \<noteq> \<emptyset>"
    by (simp add: local.consec_def)
  then show "minimum i = minimum (i \<squnion> j)"
    by (metis "1" Min_le Rep_nat_int assm el.rep_eq leD le_neq_trans local.consec_def local.minimum.rep_eq mem_Collect_eq minimum_in un_element1)
qed

(*
lemma consec_un_defined:
  "consec i j \<longrightarrow> (Rep_nat_int (i \<squnion> j) \<in> {S . (\<exists> (m::nat) n . {m..n }=S) })"
  using Rep_nat_int by auto
*)

(*
lemma consec_un_min_max:
  "consec i j \<longrightarrow> Rep_nat_int(i \<squnion> j) = {minimum i .. maximum j}"
proof
  assume assm:"consec i j"
  then have 1:"minimum j = maximum i +1"
    by (simp add: nat_int.consec_def)
  have i:"Rep_nat_int i = {minimum i..maximum i}"
    by (metis Rep_nat_int_inverse assm nat_int.consec_def nat_int.leq_max_sup' nat_int.leq_min_inf'
        rep_non_empty_means_seq)
  have j:"Rep_nat_int j = {minimum j..maximum j}"
    by (metis Rep_nat_int_inverse assm nat_int.consec_def nat_int.leq_max_sup' nat_int.leq_min_inf'
        rep_non_empty_means_seq)
  show "Rep_nat_int(i \<squnion> j) = {minimum i .. maximum j}"
    by (metis Rep_nat_int_inverse antisym assm bot.extremum i nat_int.consec_un_max
        nat_int.consec_un_min nat_int.leq_max_sup' nat_int.leq_min_inf' nat_int.un_subset1
        rep_non_empty_means_seq)
qed
*)

lemma consec_un_equality:
  "consec i j \<and> k \<noteq> \<emptyset> \<and> continuous i \<and> continuous j \<and> continuous k
    \<longrightarrow>( minimum (i \<squnion> j) = minimum (k) \<and> maximum (i \<squnion> j) = maximum (k))
      \<longrightarrow> i \<squnion> j = k"
proof (rule impI)+
  assume cons:"consec i j \<and> k \<noteq> \<emptyset> \<and> continuous i \<and> continuous j \<and> continuous k"
  assume endpoints:" minimum(i \<squnion> j) = minimum(k) \<and> maximum(i \<squnion> j) = maximum(k)"
  obtain n and m where \<open>m = minimum i\<close> and \<open>n = maximum i\<close> by blast
  obtain p and q where \<open>p = minimum j\<close> and \<open>q = maximum j\<close> by blast
  have 1:"p = n + 1" using cons consec_def
    by (simp add: \<open>n = maximum i\<close> \<open>p = minimum j\<close>)
  have 2:"\<forall>l. l \<in> {m..n} \<longleftrightarrow> l \<^bold>\<in> (i)"
    using \<open>m = minimum i\<close> \<open>n = maximum i\<close> cons consec_def continuous_nonE_atLeastAtMost by auto
  have 3:"\<forall>l. l \<in> {p..q} \<longleftrightarrow> l \<^bold>\<in> j"
    using \<open>p = minimum j\<close> \<open>q = maximum j\<close> cons consec_def continuous_nonE_atLeastAtMost by auto
  have 4:"\<forall>l. l \<in> {m..q} \<longleftrightarrow> l \<^bold>\<in> (i \<squnion> j)" using 1 2 3 cons
    by (metis Max_ge Min_le One_nat_def Rep_nat_int Suc_leI Un_iff \<open>m = minimum i\<close> \<open>q = maximum j\<close> add.right_neutral add_Suc_right atLeastAtMost_iff consec_un_max consec_un_min le_eq_less_or_eq local.el.rep_eq local.maximum.rep_eq local.minimum.rep_eq mem_Collect_eq not_less_iff_gr_or_eq sup_nat_int.rep_eq)
  then have "\<forall>l. l \<in> {m..q} \<longleftrightarrow> l \<^bold>\<in> k"
    using \<open>m = minimum i\<close> \<open>q = maximum j\<close> cons consec_un_max consec_un_min continuous_nonE_atLeastAtMost endpoints by auto
  then have "\<forall> l. l \<^bold>\<in> k \<longleftrightarrow> l\<^bold>\<in> (i \<squnion> j)"
    using "4" by blast
  then show "i \<squnion> j = k" using in_eq by auto
  (*have "Rep_nat_int( i \<squnion> j) = {minimum(i \<squnion> j)..maximum(i \<squnion> j)}"
    by (metis cons leq_max_sup leq_min_inf local.consec_def nat_int.un_element2
        nat_int.maximum.rep_eq nat_int.minimum_def nat_int.non_empty_elem_in rep_non_empty_means_seq)
  then have 1:"Rep_nat_int( i \<squnion> j) = {minimum(k) .. maximum(k)}"
    using endpoints by simp
  have "Rep_nat_int( k) = {minimum(k) .. maximum(k)}"
    by (metis cons leq_max_sup leq_min_inf nat_int.maximum.rep_eq nat_int.minimum_def
        rep_non_empty_means_seq)
  then  show " i \<squnion> j = k" using 1
    by (metis Rep_nat_int_inverse)
*)
qed

lemma consec_trans_lesser:
  "consec i j \<and> consec j k \<longrightarrow> (\<forall>n m. (n \<^bold>\<in> i \<and> m \<^bold>\<in> k \<longrightarrow> n < m))"
proof (rule allI|rule impI)+
  assume cons:" consec i j \<and> consec j k"
  fix n and m
  assume assump:"n \<^bold>\<in> i \<and> m \<^bold>\<in> k "
  have "\<forall>k . k \<^bold>\<in> j \<longrightarrow> k < m" using consec_lesser assump cons by blast
  hence m_greater:"maximum j < m" using cons maximum_in consec_def by blast
  then show "n < m"
    by (metis assump cons consec_def dual_order.strict_trans nat_int.consec_lesser
        nat_int.maximum_in)
qed

lemma consec_inter_empty:"consec i j \<Longrightarrow> i \<sqinter> j = \<emptyset>"
proof -
  assume "consec i j"
  then have "i \<noteq> bot \<and> j \<noteq> bot \<and> maximum i + 1 = minimum j"
    using consec_def by force
  then have "\<forall>n. n \<^bold>\<in> i \<longrightarrow> n \<^bold>\<notin> j" and "\<forall>n. n \<^bold>\<in> j \<longrightarrow> n \<^bold>\<notin> i"
    using \<open>consec i j\<close> consec_in_exclusive1 consec_in_exclusive2 by blast+
  then have 1:"\<not> (\<exists>n. n \<^bold>\<in> i \<and> n \<^bold>\<in> j)"
    using in_not_in_iff1 by blast
   show ?thesis
   proof (rule ccontr)
     assume "i \<sqinter> j \<noteq> \<emptyset>"
     then obtain m where "m \<^bold>\<in> i \<sqinter> j"
       using non_empty_elem_in by auto
     then have "m  \<^bold>\<in> i \<and> m \<^bold>\<in> j"
       by (simp add: inf_nat_int.rep_eq)
     then show False using 1 by blast
   qed
qed

lemma consec_intermediate1:"consec j k \<and> consec i (j \<squnion> k) \<longrightarrow> consec i j "
proof
  assume assm:"consec j k \<and> consec i (j \<squnion> k)"
  hence min_max_yz:"maximum j +1=minimum k" using consec_def by blast
  hence min_max_xyz:"maximum i +1 = minimum (j \<squnion> k)"
      using consec_def assm by blast
  have min_y_yz:"minimum j = minimum (j \<squnion> k)"
    by (simp add: assm nat_int.consec_un_min)
  hence min_max_xy:"maximum i+1 = minimum j"
    using min_max_xyz by simp
  thus consec_x_y:"consec i j" using assm consec_def by auto
qed

lemma consec_intermediate2:"consec i j \<and> consec (i \<squnion> j) k \<longrightarrow> consec j k "
proof
  assume assm:"consec i j \<and> consec (i \<squnion> j) k"
  hence min_max_yz:"maximum i +1=minimum j" using consec_def by blast
  hence min_max_xyz:"maximum (i \<squnion> j) +1 = minimum ( k)"
      using consec_def assm by blast
  have min_y_yz:"maximum j = maximum (i \<squnion> j)"
    using assm nat_int.consec_un_max by blast
  then have min_max_xy:"maximum j+1 = minimum k"
    using min_max_xyz by simp
  thus consec_x_y:"consec j k" using assm consec_def by auto
qed

lemma un_assoc: "consec i j \<and> consec j k \<longrightarrow> (i \<squnion> j) \<squnion> k = i \<squnion> (j \<squnion> k)"
  by (simp add: inf_sup_aci(6))
(*proof
  assume assm:"consec i j \<and> consec j k"
  from assm have 3:"maximum (i \<squnion> j) = maximum j"
    using nat_int.consec_un_max by auto
  from assm have 4:"minimum (j \<squnion> k) = minimum (j)"
    using nat_int.consec_un_min by auto
  have "i \<squnion> j  = Abs_nat_int{minimum i .. maximum j}"
    by (metis Rep_nat_int_inverse assm nat_int.consec_un_min_max)
  then have 5:"(i \<squnion> j) \<squnion> k = Abs_nat_int{minimum i .. maximum k}"
    by (metis (no_types, hide_lams) "3" Rep_nat_int_inverse antisym assm bot.extremum
        nat_int.consec_def nat_int.consec_un_min nat_int.consec_un_min_max nat_int.un_subset1)
  have "j \<squnion> k = Abs_nat_int{minimum j .. maximum k}"
    by (metis Rep_nat_int_inverse assm nat_int.consec_un_min_max)
  then have 6:"i \<squnion> (j \<squnion> k) = Abs_nat_int{minimum i .. maximum k}"
    by (metis (no_types, hide_lams) "4" Rep_nat_int_inverse antisym assm bot.extremum
        nat_int.consec_def nat_int.consec_un_max nat_int.consec_un_min_max nat_int.un_subset2)
  from 5 and 6 show " (i \<squnion> j) \<squnion> k = i \<squnion> (j \<squnion> k)" by simp
qed
*)

lemma consec_assoc1:"consec j k \<and> consec i (j \<squnion> k) \<longrightarrow> consec (i \<squnion> j) k "
proof
  assume assm:"consec j k \<and> consec i (j \<squnion> k)"
  hence min_max_yz:"maximum j +1=minimum k" using consec_def by blast
  hence min_max_xyz:"maximum i +1 = minimum (j \<squnion> k)"
      using consec_def assm by blast
  have min_y_yz:"minimum j = minimum (j \<squnion> k)"
    by (simp add: assm nat_int.consec_un_min)
  hence min_max_xy:"maximum i+1 = minimum j" using min_max_xyz by simp
  hence consec_x_y:"consec i j" using assm _consec_def by auto
  hence max_y_xy:"maximum j = maximum (i \<squnion> j)" using consec_lesser assm
    by (simp add: nat_int.consec_un_max)
  have none_empty:"i \<noteq> \<emptyset> \<and> j \<noteq> \<emptyset> \<and> k \<noteq> \<emptyset>" using assm by (simp add: consec_def)
  hence un_non_empty:"i\<squnion>j \<noteq> \<emptyset>"
    using bot.extremum_uniqueI consec_x_y  by force
  have max:"maximum (i\<squnion>j) +1 = minimum k"
    using min_max_yz max_y_xy by auto
  thus "consec (i \<squnion> j) k"  using max un_non_empty none_empty consec_def by blast
qed

lemma consec_assoc2:"consec i j \<and> consec (i\<squnion> j) k \<longrightarrow> consec i  (j\<squnion> k) "
proof
  assume assm:"consec i j \<and> consec (i\<squnion> j) k"
  hence consec_y_z:"consec j k" using assm consec_def consec_intermediate2
    by blast
  hence max_y_xy:"maximum j = maximum (i \<squnion> j)"
    by (simp add: assm nat_int.consec_un_max)
  have min_y_yz:"minimum j = minimum (j \<squnion> k)"
    by (simp add: consec_y_z nat_int.consec_un_min)
  have none_empty:"i \<noteq> \<emptyset> \<and> j \<noteq> \<emptyset> \<and> k \<noteq> \<emptyset>" using assm by (simp add: consec_def)
  then have un_non_empty:"j\<squnion>k \<noteq> \<emptyset>"
    by simp
  have max:"maximum (i) +1 = minimum (j\<squnion> k)"
    using assm min_y_yz consec_def by auto
  thus "consec i ( j \<squnion> k)"  using max un_non_empty none_empty consec_def by blast
qed

lemma consec_assoc_mult:
  "(i2=\<emptyset>\<or> consec i1 i2 ) \<and> (i3 =\<emptyset> \<or> consec i3 i4) \<and> (consec (i1 \<squnion> i2) (i3 \<squnion> i4))
      \<longrightarrow> (i1 \<squnion> i2) \<squnion> (i3 \<squnion> i4) = (i1 \<squnion> (i2 \<squnion> i3)) \<squnion> i4"
  by (simp add: inf_sup_aci(6))
(*proof
  assume assm:"(i2=\<emptyset>\<or> consec i1 i2 ) \<and> (i3 =\<emptyset> \<or> consec i3 i4)
                \<and> (consec (i1 \<squnion> i2) (i3 \<squnion> i4))"
  hence "(i2=\<emptyset>\<or> consec i1 i2 )" by simp
  thus " (i1 \<squnion> i2) \<squnion> (i3 \<squnion> i4) = (i1 \<squnion> (i2 \<squnion> i3)) \<squnion> i4"
  proof
    assume empty2:"i2 = \<emptyset>"
    hence only_l1:"(i1 \<squnion> i2) = i1" using un_empty_absorb1 by simp
    from assm have "(i3 =\<emptyset> \<or> consec i3 i4)" by simp
    thus " (i1 \<squnion> i2) \<squnion> (i3 \<squnion> i4) = (i1 \<squnion> (i2 \<squnion> i3)) \<squnion> i4"
      by (metis Rep_nat_int_inverse assm bot_nat_int.rep_eq empty2 local.union_def
          nat_int.consec_intermediate1 nat_int.un_assoc only_l1 sup_bot.left_neutral)
  next
    assume consec12:" consec i1 i2"
    from assm have "(i3 =\<emptyset> \<or> consec i3 i4)" by simp
    thus " (i1 \<squnion> i2) \<squnion> (i3 \<squnion> i4) = (i1 \<squnion> (i2 \<squnion> i3)) \<squnion> i4"
    proof
      assume empty3:"i3 = \<emptyset>"
      hence only_l4:"(i3 \<squnion> i4) = i4 " using un_empty_absorb2 by simp
      have "(i1 \<squnion> (i2 \<squnion> i3)) = i1 \<squnion> i2" using empty3 by (simp add: un_empty_absorb1)
      thus ?thesis by (simp add: only_l4)
    next
      assume  consec34:" consec i3 i4"
      have consec12_3:"consec (i1 \<squnion> i2) i3"
        using assm consec34 consec_intermediate1 by blast
      show ?thesis
        by (metis consec12 consec12_3 consec34 consec_intermediate2 un_assoc)
    qed
  qed
qed
*)
lemma card_subset_le: "i \<sqsubseteq> i' \<longrightarrow> |i| \<le> |i'|"
  using Rep_nat_int card_mono less_eq_nat_int.rep_eq by auto
(*  by (metis bot_nat_int.rep_eq card_mono finite.intros(1) finite_atLeastAtMost
      less_eq_nat_int.rep_eq local.card'.rep_eq ) *)

lemma card_subset_less:"(i::nat_int) < i' \<longrightarrow> |i|<|i'|"
  by (metis Rep_nat_int card'.rep_eq less_nat_int.rep_eq mem_Collect_eq psubset_card_mono)
(*
  by (metis bot_nat_int.rep_eq finite.intros(1) finite_atLeastAtMost less_nat_int.rep_eq
      local.card'.rep_eq psubset_card_mono rep_non_empty_means_seq)
*)

lemma card_empty_zero:"|\<emptyset>| = 0"
  using Abs_nat_int_inverse  card'.rep_eq bot_nat_int.rep_eq by auto

lemma card_non_empty_geq_one:"i \<noteq> \<emptyset> \<longleftrightarrow> |i| \<ge> 1"
  by (metis (full_types) One_nat_def Suc_leI bot.extremum  card_empty_zero card_subset_less le_neq_trans less_le_trans neq0_conv zero_less_one)
(*proof
  assume "i \<noteq> \<emptyset>"
  hence "Rep_nat_int i \<noteq> {}" by (metis Rep_nat_int_inverse bot_nat_int.rep_eq)
  hence "card (Rep_nat_int i) > 0"
    by (metis \<open>i \<noteq> \<emptyset>\<close> card_0_eq finite_atLeastAtMost gr0I rep_non_empty_means_seq)
  thus "|i| \<ge> 1" by (simp add: card'_def)
next
  assume "|i| \<ge> 1" thus "i \<noteq>\<emptyset>"
    using card_empty_zero by auto
qed
*)

lemma card_min_max:"continuous i \<and> i \<noteq> \<emptyset> \<longrightarrow> |i| = (maximum i - minimum i) + 1"
proof
  assume "continuous i \<and> i \<noteq> \<emptyset>"
  then have "\<forall>l. l \<in> {minimum i .. maximum i} \<longleftrightarrow> l \<^bold>\<in> i"
    using continuous_nonE_atLeastAtMost by blast
  then have 1:"|i| = card {minimum i..maximum i}"
    by (metis antisym card'.rep_eq el.rep_eq subsetI)
  have "card {minimum i..maximum i} = (maximum i - minimum i) + 1"
    using \<open>continuous i \<and> i \<noteq> bot\<close> \<open>|i| = card {minimum i..maximum i}\<close> card_non_empty_geq_one by force
  then show "  |i| = (maximum i - minimum i) + 1" using 1 by auto
qed
(*proof
  assume assm:"i \<noteq> \<emptyset>"
  then have "Rep_nat_int i = {minimum i .. maximum i}"
    by (metis leq_max_sup leq_min_inf nat_int.maximum.rep_eq nat_int.minimum_def
        rep_non_empty_means_seq)
  then have "card (Rep_nat_int i) = maximum i - minimum i + 1"
    using Rep_nat_int_inject assm bot_nat_int.rep_eq by fastforce
  then show " |i| = (maximum i - minimum i) + 1"  by simp
qed
*)

lemma card_un_add:"i \<sqinter> j = \<emptyset> \<longrightarrow> |i \<squnion> j| = |i| + |j|"
  by (metis bot_nat_int.rep_eq card'.rep_eq card.infinite card_Un_disjoint card_non_empty_geq_one finite.intros(1) inf_nat_int.rep_eq not_one_le_zero sup_nat_int.rep_eq)

lemma card_un_add': " continuous i \<and> continuous j \<and> consec i j \<longrightarrow> |i \<squnion> j| = |i| + |j|"
  by (metis Rep_nat_int bot_nat_int.rep_eq card'.rep_eq card_Un_disjoint consec_inter_empty inf_nat_int.rep_eq mem_Collect_eq sup_nat_int.rep_eq)
(*proof
  assume assm:"consec i j"
  then have 0:"i \<sqinter> j = \<emptyset>"
    using nat_int.consec_inter_empty by auto
  then have "(Rep_nat_int i) \<inter> (Rep_nat_int j) = {}"
    by (metis bot_nat_int.rep_eq inf_nat_int.rep_eq)
  then have 1:
    "card((Rep_nat_int i)\<union>(Rep_nat_int j))=card(Rep_nat_int i)+card(Rep_nat_int j)"
    by (metis Int_iff add.commute add.left_neutral assm card.infinite card_Un_disjoint
        emptyE le_add1 le_antisym local.consec_def nat_int.card'.rep_eq
        nat_int.card_min_max nat_int.el.rep_eq nat_int.maximum_in nat_int.minimum_in)
  then show "|i \<squnion> j| = |i| + |j|"
  proof -
    have f1: "i \<noteq> \<emptyset> \<and> j \<noteq> \<emptyset> \<and> maximum i + 1 = minimum j"
      using assm nat_int.consec_def by blast
    then have f2: "Rep_nat_int i \<noteq> {}"
      using Rep_nat_int_inject bot_nat_int.rep_eq by auto
    have "Rep_nat_int j \<noteq> {}"
      using f1 Rep_nat_int_inject bot_nat_int.rep_eq by auto
    then show ?thesis
      using f2 f1 Abs_nat_int_inverse Rep_nat_int 1 local.union_result
        nat_int.union_def nat_int_class.maximum.rep_eq nat_int_class.minimum_def
        by force
  qed
qed
*)

lemma singleton: "|i| = 1 \<longleftrightarrow> (\<exists>n. \<forall>l. l \<in> {n} \<longleftrightarrow> l \<^bold>\<in> i)"
proof
  assume "|i| = 1"
  obtain s where "s = Rep_nat_int i"
    by simp
  then obtain m where "s = {m}"
    using \<open>|i| = 1\<close> card_1_singletonE by auto
  then show " (\<exists>n. \<forall>l. l \<in> {n} \<longleftrightarrow> l \<^bold>\<in> i)"
    using \<open>s = Rep_nat_int i\<close> by auto
next
  assume "(\<exists>n. \<forall>l. l \<in> {n} \<longleftrightarrow> l \<^bold>\<in> i)"
  then obtain n where "\<forall>l. l \<in> {n} \<longleftrightarrow> l \<^bold>\<in> i" by blast
  then show "|i| = 1" using card'.rep_eq
    by (metis all_not_in_conv el.rep_eq insertI1 is_singletonI' is_singleton_altdef singletonD)
qed

lemma atLeastAtMost_card:"(\<forall>l . l \<in> {m..n} \<longleftrightarrow> l\<^bold>\<in>i) \<longrightarrow> |i| = card {m..n}"
proof
  assume "\<forall>l . l \<in> {m..n} \<longleftrightarrow> l\<^bold>\<in>i"
  show " |i| = card {m..n}"
  proof (cases "i = \<emptyset>")
    case True
    show ?thesis
      by (metis True \<open>\<forall>l. (l \<in> {m..n}) = (l \<^bold>\<in> i)\<close> atLeastAtMost_insertL atLeastAtMost_singleton atLeastatMost_empty_iff2 bot_nat_int.rsp bot_nat_int_def card.empty card_empty_zero insertI1 insert_absorb nat_int.el.abs_eq order_refl)
  next
    case False
    have "m = minimum i"
      using False \<open>\<forall>l. (l \<in> {m..n}) = (l \<^bold>\<in> i)\<close> nat_int_atLeastAtMost_min by blast
    have "n = maximum i"
      using False \<open>\<forall>l. (l \<in> {m..n}) = (l \<^bold>\<in> i)\<close> nat_int_atLeastAtMost_max by blast
    show ?thesis
      using False \<open>\<forall>l. (l \<in> {m..n}) = (l \<^bold>\<in> i)\<close> \<open>m = minimum i\<close> \<open>n = maximum i\<close> card_min_max continuous_nonE_atLeastAtMost minimum_in by auto
  qed
qed

lemma cont_card_two:"continuous i \<longrightarrow> ( |i| = 2 \<longleftrightarrow> ( \<exists>n. \<forall> l. l \<in> {n..n+1} \<longleftrightarrow> l \<^bold>\<in> i))"
proof
  assume "continuous i"
  then obtain m  and n where 1:"\<forall>l. l \<in> {m..n} \<longleftrightarrow> l \<^bold>\<in> i"
    using continuos_atLeastAtMost by blast
  show "( |i| = 2 \<longleftrightarrow> ( \<exists>n. \<forall> l. l \<in> {n..n+1} \<longleftrightarrow> l \<^bold>\<in> i))"
  proof
    assume "|i| = 2"
    then have "card {m..n} = 2"
      using "1" atLeastAtMost_card by auto
    then have "n = m+1"
      by simp
    then show " \<exists>n. \<forall> l. l \<in> {n..n+1} \<longleftrightarrow> l \<^bold>\<in> i" using 1 by blast
  next
    assume " \<exists>n. \<forall> l. l \<in> {n..n+1} \<longleftrightarrow> l \<^bold>\<in> i"
    then obtain k where 2:"\<forall> l. l \<in> {k..k+1} \<longleftrightarrow> l \<^bold>\<in> i" by blast
    then show "|i| = 2" using atLeastAtMost_card
      using card_atLeastAtMost by presburger
  qed
qed

lemma cont_card_two':"continuous i \<longrightarrow> ( |i| = 2 \<longleftrightarrow> ( \<exists>n. \<forall> l. l \<in> {n,n+1} \<longleftrightarrow> l \<^bold>\<in> i))"
proof -
  have 1:"\<forall>n::nat. {n..n+1} = {n,n+1}"
    by (simp add: atLeastAtMostSuc_conv insert_commute)
  show ?thesis using cont_card_two 1
    by (metis Suc_eq_plus1 )
qed

lemma subset_card_two: "continuous i \<and> continuous j \<and> (j \<noteq> \<emptyset>) \<and> (j \<sqsubseteq> i)  \<longrightarrow> ( \<exists>n. ( \<forall> l. l \<in> {n,n+1} \<longleftrightarrow> l \<^bold>\<in> i) \<longrightarrow> n \<^bold>\<in> j \<or> (n+1) \<^bold>\<in> j)  "
  by auto
(*lemma singleton:"|i| = 1 \<longrightarrow> (\<exists>n. Rep_nat_int i = {n})"
  using card_1_singletonE card'.rep_eq by fastforce

lemma singleton2:" (\<exists>n. Rep_nat_int i = {n}) \<longrightarrow> |i| = 1"
  using card_1_singletonE card'.rep_eq by fastforce
*)

(*