Hello,

Is there a process to propose extensions to the Isabelle library? Is isabelle-dev the right place, as opposed to isabelle-users?

As part of an Isabelle project, I've developed some type classes and theorems for orders and lattices (see attached file) that could be of general use.

Thank you in advance!

theory LibExt
imports Main
begin


section {* Library Extensions *}


subsection {* Notations *}

text {* Standard mathematical notations for various operators are introduced. *}

notation
 bot ("\<bottom>") and
 top ("\<top>") and
 inf (infixl "\<sqinter>" 70) and
 sup (infixl "\<squnion>" 65) and
 Inf ("\<Sqinter>_" [900] 900) and
 Sup ("\<Squnion>_" [900] 900)


subsection {* Orders *}

text {* Given two ordered types,
their product type can be ordered component-wise. *}

definition leq_leq :: "'a::ord \<times> 'b::ord \<Rightarrow> 'a \<times> 'b 
\<Rightarrow> bool"
where "leq_leq x y \<equiv> fst x \<le> fst y \<and> snd x \<le> snd y"

instantiation prod :: (ord, ord) ord
begin
definition "less_eq_prod \<equiv> leq_leq"
definition "less_prod x y \<equiv> leq_leq x y \<and> \<not> leq_leq y x"
instance
proof qed
end


subsection {* Preorders *}

text {* The product of two preorders is a preorder. *}

lemma leq_leq_refl: "(x::'a::preorder \<times> 'b::preorder) \<le> x"
by (metis leq_leq_def less_eq_prod_def order_refl)

lemma leq_leq_trans: "(x::'a::preorder \<times> 'b::preorder) \<le> y 
\<Longrightarrow> y \<le> z \<Longrightarrow> x \<le> z"
by (metis (full_types) leq_leq_def less_eq_prod_def order_trans)

instance prod :: (preorder, preorder) preorder
apply (intro_classes)
apply (metis less_prod_def less_eq_prod_def)
apply (metis leq_leq_refl)
apply (metis leq_leq_trans)
done


subsection {* Partial Orders *}

text {* The product of two partial orders is a partial order. *}

lemma leq_leq_antisym: "(x::'a::order \<times> 'b::order) \<le> y 
\<Longrightarrow> x \<ge> y \<Longrightarrow> x = y"
by (metis leq_leq_def less_eq_prod_def order_eq_iff prod_eqI)

instance prod :: (order, order) order
proof qed (metis leq_leq_antisym)


subsection {* Lattices *}

text {* Given two types with infimum or supremum,
the infimum or supremum for their product can be defined component-wise. *}

definition inf_inf :: "'a::inf \<times> 'b::inf \<Rightarrow> 'a \<times> 'b 
\<Rightarrow> 'a \<times> 'b"
where "inf_inf x y \<equiv> (fst x \<sqinter> fst y, snd x \<sqinter> snd y)"

definition sup_sup :: "'a::sup \<times> 'b::sup \<Rightarrow> 'a \<times> 'b 
\<Rightarrow> 'a \<times> 'b"
where "sup_sup x y \<equiv> (fst x \<squnion> fst y, snd x \<squnion> snd y)"

instantiation prod :: (inf, inf) inf
begin
definition "inf_prod \<equiv> inf_inf"
instance
proof qed
end

instantiation prod :: (sup, sup) sup
begin
definition "sup_prod \<equiv> sup_sup"
instance
proof qed
end

text {* The product of two semilattices is a semilattice. *}

lemma inf_inf_le1: "(x::'a::semilattice_inf \<times> 'b::semilattice_inf) 
\<sqinter> y \<le> x"
unfolding inf_prod_def inf_inf_def
using inf_le1
by (metis Pair_eq leq_leq_def less_eq_prod_def surjective_pairing)

lemma inf_inf_le2: "(x::'a::semilattice_inf \<times> 'b::semilattice_inf) 
\<sqinter> y \<le> y"
unfolding inf_prod_def inf_inf_def
using inf_le2
by (metis Pair_eq leq_leq_def less_eq_prod_def surjective_pairing)

lemma inf_inf_greatest:
"(x::'a::semilattice_inf \<times> 'b::semilattice_inf) \<le> y 
\<Longrightarrow> x \<le> z \<Longrightarrow> x \<le> y \<sqinter> z"
unfolding inf_prod_def inf_inf_def less_eq_prod_def leq_leq_def
by (metis fst_eqD le_inf_iff snd_eqD)

instance prod :: (semilattice_inf, semilattice_inf) semilattice_inf
proof qed (auto simp: inf_inf_le1 inf_inf_le2 inf_inf_greatest)

lemma sup_sup_ge1: "(x::'a::semilattice_sup \<times> 'b::semilattice_sup) 
\<squnion> y \<ge> x"
unfolding sup_prod_def sup_sup_def
using sup_ge1
by (metis Pair_eq leq_leq_def less_eq_prod_def surjective_pairing)

lemma sup_sup_ge2: "(x::'a::semilattice_sup \<times> 'b::semilattice_sup) 
\<squnion> y \<ge> y"
unfolding sup_prod_def sup_sup_def
using sup_ge2
by (metis Pair_eq leq_leq_def less_eq_prod_def surjective_pairing)

lemma sup_sup_least:
"(x::'a::semilattice_sup \<times> 'b::semilattice_sup) \<ge> y 
\<Longrightarrow> x \<ge> z \<Longrightarrow> x \<ge> y \<squnion> z"
unfolding sup_prod_def sup_sup_def less_eq_prod_def leq_leq_def
by (metis fst_eqD le_sup_iff snd_eqD)

instance prod :: (semilattice_sup, semilattice_sup) semilattice_sup
proof qed (auto simp: sup_sup_ge1 sup_sup_ge2 sup_sup_least)

text {* The product of two lattices is a lattice. *}

instance prod :: (lattice, lattice) lattice
proof qed


subsection {* Distributive Lattices *}

text {* The product of two distributive lattices is a distributive lattice. *}

lemma sup_sup_inf_inf_distrib1:
"(x::'a::distrib_lattice \<times> 'b::distrib_lattice) \<squnion> (y \<sqinter> 
z) = (x \<squnion> y) \<sqinter> (x \<squnion> z)"
unfolding inf_prod_def inf_inf_def sup_prod_def sup_sup_def
by (metis fst_eqD snd_eqD sup_inf_distrib1)

instance prod :: (distrib_lattice, distrib_lattice) distrib_lattice
proof qed (metis sup_sup_inf_inf_distrib1)


subsection {* Bounded Lattices *}

text {* Given two types with bottom or top,
the bottom or top of their product is defined component-wise. *}

definition bot_bot :: "'a::bot \<times> 'b::bot"
where "bot_bot \<equiv> (\<bottom>, \<bottom>)"

definition top_top :: "'a::top \<times> 'b::top"
where "top_top \<equiv> (\<top>, \<top>)"

instantiation prod :: (bot, bot) bot
begin
definition "bot_prod \<equiv> bot_bot"
instance
proof qed (auto simp: bot_prod_def bot_bot_def leq_leq_def less_eq_prod_def)
end

instantiation prod :: (top, top) top
begin
definition "top_prod \<equiv> top_top"
instance
proof qed (auto simp: top_prod_def top_top_def leq_leq_def less_eq_prod_def)
end

text {* The product of two bounded lattices is a bounded lattice. *}

instance prod :: (bounded_lattice, bounded_lattice) bounded_lattice
proof qed


subsection {* Complete Lattices *}

text {* Given two types with set infimum or supremum,
the set infimum or supremum for their product can be defined component-wise. *}

definition Inf_Inf :: "('a::Inf \<times> 'b::Inf) set \<Rightarrow> 'a \<times> 
'b"
where "Inf_Inf A \<equiv> (\<Sqinter> (fst ` A), \<Sqinter> (snd ` A))"

definition Sup_Sup :: "('a::Sup \<times> 'b::Sup) set \<Rightarrow> 'a \<times> 
'b"
where "Sup_Sup A \<equiv> (\<Squnion> (fst ` A), \<Squnion> (snd ` A))"

instantiation prod :: (Inf, Inf) Inf
begin
definition "Inf_prod \<equiv> Inf_Inf"
instance
proof qed
end

instantiation prod :: (Sup, Sup) Sup
begin
definition "Sup_prod \<equiv> Sup_Sup"
instance
proof qed
end

text {* The product of two complete lattices is a complete lattice. *}

lemma Inf_Inf_lower:
"(x::'a::complete_lattice \<times> 'b::complete_lattice) \<in> A 
\<Longrightarrow> \<Sqinter>A \<le> x"
unfolding Inf_prod_def Inf_Inf_def
by (metis Inf_lower fst_conv imageI leq_leq_def less_eq_prod_def snd_conv)

lemma Inf_Inf_greatest:
"\<forall>x::'a::complete_lattice \<times> 'b::complete_lattice \<in> A. z 
\<le> x \<Longrightarrow> z \<le> \<Sqinter>A"
unfolding Inf_prod_def Inf_Inf_def less_eq_prod_def leq_leq_def
using Inf_greatest [of "fst ` A" "fst z"] Inf_greatest [of "snd ` A" "snd z"]
by (metis (hide_lams, no_types) fst_eqD image_iff snd_eqD)

lemma Sup_Sup_upper:
"(x::'a::complete_lattice \<times> 'b::complete_lattice) \<in> A 
\<Longrightarrow> \<Squnion>A \<ge> x"
unfolding Sup_prod_def Sup_Sup_def
by (metis Sup_upper fst_conv imageI leq_leq_def less_eq_prod_def snd_conv)

lemma Sup_Sup_least:
"\<forall>x::'a::complete_lattice \<times> 'b::complete_lattice \<in> A. z 
\<ge> x \<Longrightarrow> z \<ge> \<Squnion>A"
unfolding Sup_prod_def Sup_Sup_def less_eq_prod_def leq_leq_def
using Sup_least [of "fst ` A" "fst z"] Sup_least [of "snd ` A" "snd z"]
by (metis (hide_lams, no_types) fst_eqD image_iff snd_eqD)

instance prod :: (complete_lattice, complete_lattice) complete_lattice
proof
qed (auto simp: Inf_Inf_lower Inf_Inf_greatest Sup_Sup_upper Sup_Sup_least)

text {* The infimum or supremum of the image of a set,
under a function whose codomain is a product of two complete lattices,
is defined component-wise. *}

lemma INFI_INFI_alt_def:
"INFI A (f::'c \<Rightarrow> 'a::complete_lattice \<times> 
'b::complete_lattice) =
 (INFI A (fst o f), INFI A (snd o f))"
unfolding INF_def
by (metis (hide_lams, no_types) Inf_Inf_def Inf_prod_def image_compose)

lemma INF_INF_alt_def:
"(INF x:A. ((f x)::'a::complete_lattice \<times> 'b::complete_lattice)) =
 (INF x:A. fst (f x), INF x:A. snd (f x))"
by (metis (mono_tags) INFI_INFI_alt_def INF_cong o_apply)

lemma SUPR_SUPR_alt_def:
"SUPR A (f::'c \<Rightarrow> 'a::complete_lattice \<times> 
'b::complete_lattice) =
 (SUPR A (fst o f), SUPR A (snd o f))"
unfolding SUP_def
by (metis (hide_lams, no_types) Sup_Sup_def Sup_prod_def image_compose)

lemma SUP_SUP_alt_def:
"(SUP x:A. ((f x)::'a::complete_lattice \<times> 'b::complete_lattice)) =
 (SUP x:A. fst (f x), SUP x:A. snd (f x))"
by (metis (mono_tags) SUPR_SUPR_alt_def SUP_cong o_apply)


subsection {* Complete Distributive Lattices *}

text {* The product of two lattices
whose @{const inf} and @{const sup} operators
distribute over @{const Sup} and @{const Inf},
is a lattice
whose @{const inf} and @{const sup} operators
distribute over @{const Sup} and @{const Inf}. *}

lemma sup_sup_Inf_Inf:
"(x::'a::complete_distrib_lattice \<times> 'b::complete_distrib_lattice) 
\<squnion> \<Sqinter>A =
 (INF y:A. x \<squnion> y)"
by (auto simp:
 sup_prod_def sup_sup_def Inf_prod_def Inf_Inf_def INF_INF_alt_def sup_Inf)

lemma inf_inf_Sup_Sup:
"(x::'a::complete_distrib_lattice \<times> 'b::complete_distrib_lattice) 
\<sqinter> \<Squnion>A =
 (SUP y:A. x \<sqinter> y)"
by (auto simp:
 inf_prod_def inf_inf_def Sup_prod_def Sup_Sup_def SUP_SUP_alt_def inf_Sup)

instance prod ::
 (complete_distrib_lattice, complete_distrib_lattice) complete_distrib_lattice
proof qed (auto simp: sup_sup_Inf_Inf inf_inf_Sup_Sup)


subsection {* Finite Lattices *}

text {* A type class for finite lattices is introduced. *}

class finite_lattice = finite + lattice

text {* A non-empty finite lattice is a complete lattice.
Since types are never empty in Isabelle/HOL,
a type of class @{class finite_lattice}
should also have class @{class complete_lattice}.
Since in Isabelle/HOL
a subclass must have all the parameters of its superclasses,
class @{class finite_lattice} cannot be a subclass of @{class complete_lattice}.
So class @{class finite_lattice} is extended with
the operators @{const bot}, @{const top}, @{const Inf}, and @{const Sup},
along with assumptions that define these operators
in terms of the ones of class @{class finite_lattice}.
The resulting class is a subclass of @{class complete_lattice}.
Classes @{class bot} and @{class top} already include assumptions that suffice
to define the operators @{const bot} and @{const top} (as proved below),
and so no explicit assumptions on these two operators are needed
in the following type class.%
\footnote{The Isabelle/HOL library does not provide
syntactic classes for the operators @{const bot} and @{const top}.} *}

class finite_lattice_complete = finite_lattice + bot + top + Inf + Sup +
assumes Inf_def: "\<Sqinter>A = Finite_Set.fold (op \<sqinter>) \<top> A"
assumes Sup_def: "\<Squnion>A = Finite_Set.fold (op \<squnion>) \<bottom> A"
-- "No explicit assumptions on @{const bot} or @{const top}."

instance finite_lattice_complete \<subseteq> bounded_lattice
proof qed
-- "This subclass relation eases the proof of the next two lemmas."

lemma finite_lattice_complete_bot_def:
"(\<bottom>::'a::finite_lattice_complete) = \<Sqinter>\<^bsub>fin\<^esub>UNIV"
by (metis finite_UNIV sup_Inf_absorb sup_bot_left iso_tuple_UNIV_I)
-- "Derived definition of @{const bot}."

lemma finite_lattice_complete_top_def:
"(\<top>::'a::finite_lattice_complete) = \<Squnion>\<^bsub>fin\<^esub>UNIV"
by (metis finite_UNIV inf_Sup_absorb inf_top_left iso_tuple_UNIV_I)
-- "Derived definition of @{const top}."

text {* The definitional assumptions
on the operators @{const Inf} and @{const Sup}
of class @{class finite_lattice_complete}
ensure that they yield infimum and supremum,
as required for a complete lattice. *}

lemma finite_lattice_complete_Inf_lower:
"(x::'a::finite_lattice_complete) \<in> A \<Longrightarrow> \<Sqinter>A \<le> x"
unfolding Inf_def
by (metis finite_code le_inf_iff fold_inf_le_inf)

lemma finite_lattice_complete_Inf_greatest:
"\<forall>x::'a::finite_lattice_complete \<in> A. z \<le> x \<Longrightarrow> z 
\<le> \<Sqinter>A"
unfolding Inf_def
by (metis finite_code inf_le_fold_inf inf_top_right)

lemma finite_lattice_complete_Sup_upper:
"(x::'a::finite_lattice_complete) \<in> A \<Longrightarrow> \<Squnion>A \<ge> x"
unfolding Sup_def
by (metis finite_code le_sup_iff sup_le_fold_sup)

lemma finite_lattice_complete_Sup_least:
"\<forall>x::'a::finite_lattice_complete \<in> A. z \<ge> x \<Longrightarrow> z 
\<ge> \<Squnion>A"
unfolding Sup_def
by (metis finite_code fold_sup_le_sup sup_bot_right)

instance finite_lattice_complete \<subseteq> complete_lattice
proof
qed (auto simp:
 finite_lattice_complete_Inf_lower
 finite_lattice_complete_Inf_greatest
 finite_lattice_complete_Sup_upper
 finite_lattice_complete_Sup_least)

text {* The product of two finite lattices is a finite lattice. *}

instance prod :: (finite_lattice, finite_lattice) finite_lattice
proof qed

lemma finite_Inf_Inf:
"\<Sqinter>(A::('a::finite_lattice_complete \<times> 
'b::finite_lattice_complete) set) =
 Finite_Set.fold (op \<sqinter>) \<top> A"
by (metis Inf_fold_inf finite_code)

lemma finite_Sup_Sup:
"\<Squnion>(A::('a::finite_lattice_complete \<times> 
'b::finite_lattice_complete) set) =
 Finite_Set.fold (op \<squnion>) \<bottom> A"
by (metis Sup_fold_sup finite_code)

instance prod ::
 (finite_lattice_complete, finite_lattice_complete) finite_lattice_complete
proof qed (auto simp: finite_Inf_Inf finite_Sup_Sup)

text {* Functions with a finite domain and with a finite lattice as codomain
form a finite lattice. *}

instance "fun" :: (finite, finite_lattice) finite_lattice
proof qed

lemma finite_Inf_fun:
"\<Sqinter>(A::('a::finite \<Rightarrow> 'b::finite_lattice_complete) set) =
 Finite_Set.fold (op \<sqinter>) \<top> A"
by (metis Inf_fold_inf finite_code)

lemma finite_Sup_fun:
"\<Squnion>(A::('a::finite \<Rightarrow> 'b::finite_lattice_complete) set) =
 Finite_Set.fold (op \<squnion>) \<bottom> A"
by (metis Sup_fold_sup finite_code)

instance "fun" :: (finite, finite_lattice_complete) finite_lattice_complete
proof qed (auto simp: finite_Inf_fun finite_Sup_fun)


subsection {* Finite Distributive Lattices *}

text {* A type class for finite distributive lattices is introduced. *}

class finite_distrib_lattice = finite + distrib_lattice

text {* A finite distributive lattice is a complete lattice
whose @{const inf} and @{const sup} operators
distribute over @{const Sup} and @{const Inf}. *}

class finite_distrib_lattice_complete =
 finite_distrib_lattice + finite_lattice_complete

lemma finite_distrib_lattice_complete_sup_Inf:
"(x::'a::finite_distrib_lattice_complete) \<squnion> \<Sqinter>A = (INF y:A. x 
\<squnion> y)"
apply (rule finite_induct)
apply (metis finite_code)
apply (metis INF_empty Inf_empty sup_top_right)
apply (metis INF_insert Inf_insert sup_inf_distrib1)
done

lemma finite_distrib_lattice_complete_inf_Sup:
"(x::'a::finite_distrib_lattice_complete) \<sqinter> \<Squnion>A = (SUP y:A. x 
\<sqinter> y)"
 apply (rule finite_induct)
 apply (metis finite_code)
 apply (metis SUP_empty Sup_empty inf_bot_right)
 apply (metis SUP_insert Sup_insert inf_sup_distrib1)
done

instance finite_distrib_lattice_complete \<subseteq> complete_distrib_lattice
proof
qed (auto simp:
 finite_distrib_lattice_complete_sup_Inf
 finite_distrib_lattice_complete_inf_Sup)

text {* The product of two finite distributive lattices
is a finite distributive lattice. *}

instance prod ::
 (finite_distrib_lattice, finite_distrib_lattice) finite_distrib_lattice
proof qed

instance prod ::
 (finite_distrib_lattice_complete, finite_distrib_lattice_complete)
 finite_distrib_lattice_complete
proof qed

text {* Functions with a finite domain
and with a finite distributive lattice as codomain
form a finite distributive lattice. *}

instance "fun" :: (finite, finite_distrib_lattice) finite_distrib_lattice
proof qed

instance "fun" ::
 (finite, finite_distrib_lattice_complete) finite_distrib_lattice_complete
proof qed


subsection {* Linear Orders *}

text {* A linear order is a distributive lattice.
Since in Isabelle/HOL
a subclass must have all the parameters of its superclasses,
class @{class linorder} cannot be a subclass of @{class distrib_lattice}.
So class @{class linorder} is extended with
the operators @{const inf} and @{const sup},
along with assumptions that define these operators
in terms of the ones of class @{class linorder}.
The resulting class is a subclass of @{class distrib_lattice}. *}

class linorder_lattice = linorder + inf + sup +
assumes inf_def: "x \<sqinter> y = (if x \<le> y then x else y)"
assumes sup_def: "x \<squnion> y = (if x \<ge> y then x else y)"

text {* The definitional assumptions
on the operators @{const inf} and @{const sup}
of class @{class linorder_lattice}
ensure that they yield infimum and supremum,
and that they distribute over each other,
as required for a distributive lattice. *}

lemma linorder_lattice_inf_le1:
"(x::'a::linorder_lattice) \<sqinter> y \<le> x"
unfolding inf_def
by (metis (full_types) linorder_linear)

lemma linorder_lattice_inf_le2:
"(x::'a::linorder_lattice) \<sqinter> y \<le> y"
unfolding inf_def
by (metis (full_types) linorder_linear)

lemma linorder_lattice_inf_greatest:
"(x::'a::linorder_lattice) \<le> y \<Longrightarrow> x \<le> z 
\<Longrightarrow> x \<le> y \<sqinter> z"
unfolding inf_def
by (metis (full_types))

lemma linorder_lattice_sup_ge1:
"(x::'a::linorder_lattice) \<squnion> y \<ge> x"
unfolding sup_def
by (metis (full_types) linorder_linear)

lemma linorder_lattice_sup_ge2:
"(x::'a::linorder_lattice) \<squnion> y \<ge> y"
unfolding sup_def
by (metis (full_types) linorder_linear)

lemma linorder_lattice_sup_least:
"(x::'a::linorder_lattice) \<ge> y \<Longrightarrow> x \<ge> z 
\<Longrightarrow> x \<ge> y \<squnion> z"
unfolding sup_def
by (metis (full_types))

lemma linorder_lattice_sup_inf_distrib1:
"(x::'a::linorder_lattice) \<squnion> y \<sqinter> z = (x \<squnion> y) 
\<sqinter> (x \<squnion> z)"
by (auto simp: inf_def sup_def)
 
instance linorder_lattice \<subseteq> distrib_lattice
proof                                                     
qed (auto simp:
 linorder_lattice_inf_le1
 linorder_lattice_inf_le2
 linorder_lattice_inf_greatest
 linorder_lattice_sup_ge1
 linorder_lattice_sup_ge2
 linorder_lattice_sup_least
 linorder_lattice_sup_inf_distrib1)


subsection {* Finite Linear Orders *}

text {* A type class for finite linear orders is introduced. *}

class finite_linorder = finite + linorder

text {* A finite linear order is a finite distributive lattice. *}

class finite_linorder_lattice = finite_linorder + linorder_lattice

instance finite_linorder_lattice \<subseteq> finite_distrib_lattice
proof qed

text {* A (non-empty) finite linear order is a complete linear order. *}

class finite_linorder_complete =
 finite_linorder_lattice + finite_lattice_complete

instance finite_linorder_complete \<subseteq> complete_linorder
proof qed

text {* A (non-empty) finite linear order is a complete lattice
whose @{const inf} and @{const sup} operators
distribute over @{const Sup} and @{const Inf}. *}

instance finite_linorder_complete \<subseteq> finite_distrib_lattice_complete
proof qed

instance finite_linorder_complete \<subseteq> complete_distrib_lattice
proof qed


end

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature

_______________________________________________
isabelle-dev mailing list
isabelle-...@in.tum.de
https://mailmanbroy.informatik.tu-muenchen.de/mailman/listinfo/isabelle-dev

Reply via email to