# Theory Basic_Extensions

```section ‹Basics›

theory Basic_Extensions
imports "HOL-Library.Infinite_Set"
begin

subsection ‹Types›

type_synonym 'a step = "'a ⇒ 'a"

subsection ‹Rules›

declare less_imp_le[dest, simp]

declare le_funI[intro]
declare le_funE[elim]
declare le_funD[dest]

lemma IdI'[intro]:
assumes "x = y"
shows "(x, y) ∈ Id"
using assms by auto

lemma (in order) order_le_cases:
assumes "x ≤ y"
obtains (eq) "x = y" | (lt) "x < y"
using assms le_less by auto

lemma (in linorder) linorder_cases':
obtains (le) "x ≤ y" | (gt) "x > y"
by force

lemma monoI_comp[intro]:
assumes "mono f" "mono g"
shows "mono (f ∘ g)"
using assms by (intro monoI, auto dest: monoD)
lemma strict_monoI_comp[intro]:
assumes "strict_mono f" "strict_mono g"
shows "strict_mono (f ∘ g)"
using assms by (intro strict_monoI, auto dest: strict_monoD)

lemma eq_le_absorb[simp]:
fixes x y :: "'a :: order"
shows "x = y ∧ x ≤ y ⟷ x = y" "x ≤ y ∧ x = y ⟷ x = y"
by auto

lemma INFM_Suc[simp]: "(∃⇩∞ i. P (Suc i)) ⟷ (∃⇩∞ i. P i)"
unfolding INFM_nat using Suc_lessE less_Suc_eq by metis
lemma INFM_plus[simp]: "(∃⇩∞ i. P (i + n :: nat)) ⟷ (∃⇩∞ i. P i)"
proof (induct n)
case 0
show ?case by simp
next
case (Suc n)
have "(∃⇩∞ i. P (i + Suc n)) ⟷ (∃⇩∞ i. P (Suc i + n))" by simp
also have "… ⟷ (∃⇩∞ i. P (i + n))" using INFM_Suc by this
also have "… ⟷ (∃⇩∞ i. P i)" using Suc by this
finally show ?case by this
qed
lemma INFM_minus[simp]: "(∃⇩∞ i. P (i - n :: nat)) ⟷ (∃⇩∞ i. P i)"
proof (induct n)
case 0
show ?case by simp
next
case (Suc n)
have "(∃⇩∞ i. P (i - Suc n)) ⟷ (∃⇩∞ i. P (Suc i - Suc n))" using INFM_Suc by meson
also have "… ⟷ (∃⇩∞ i. P (i - n))" by simp
also have "… ⟷ (∃⇩∞ i. P i)" using Suc by this
finally show ?case by this
qed

subsection ‹Constants›

definition const :: "'a ⇒ 'b ⇒ 'a"
where "const x ≡ λ _. x"
definition const2 :: "'a ⇒ 'b ⇒ 'c ⇒ 'a"
where "const2 x ≡ λ _ _. x"
definition const3 :: "'a ⇒ 'b ⇒ 'c ⇒ 'd ⇒ 'a"
where "const3 x ≡ λ _ _ _. x"
definition const4 :: "'a ⇒ 'b ⇒ 'c ⇒ 'd ⇒ 'e ⇒ 'a"
where "const4 x ≡ λ _ _ _ _. x"
definition const5 :: "'a ⇒ 'b ⇒ 'c ⇒ 'd ⇒ 'e ⇒ 'f ⇒ 'a"
where "const5 x ≡ λ _ _ _ _ _. x"

lemma const_apply[simp]: "const x y = x" unfolding const_def by rule
lemma const2_apply[simp]: "const2 x y z = x" unfolding const2_def by rule
lemma const3_apply[simp]: "const3 x y z u = x" unfolding const3_def by rule
lemma const4_apply[simp]: "const4 x y z u v = x" unfolding const4_def by rule
lemma const5_apply[simp]: "const5 x y z u v w = x" unfolding const5_def by rule

definition zip_fun :: "('a ⇒ 'b) ⇒ ('a ⇒ 'c) ⇒ 'a ⇒ 'b × 'c" (infixr "∥" 51)
where "f ∥ g ≡ λ x. (f x, g x)"

lemma zip_fun_simps[simp]:
"(f ∥ g) x = (f x, g x)"
"fst ∘ (f ∥ g) = f"
"snd ∘ (f ∥ g) = g"
"fst ∘ h ∥ snd ∘ h = h"
"fst ` range (f ∥ g) = range f"
"snd ` range (f ∥ g) = range g"
unfolding zip_fun_def by force+

lemma zip_fun_eq[dest]:
assumes "f ∥ g = h ∥ i"
shows "f = h" "g = i"
using assms unfolding zip_fun_def by (auto dest: fun_cong)

lemma zip_fun_range_subset[intro, simp]: "range (f ∥ g) ⊆ range f × range g"
unfolding zip_fun_def by blast
lemma zip_fun_range_finite[elim]:
assumes "finite (range (f ∥ g))"
obtains "finite (range f)" "finite (range g)"
proof
show "finite (range f)" using finite_imageI [OF assms(1), of fst]
show "finite (range g)" using finite_imageI [OF assms(1), of snd]
qed

lemma zip_fun_split:
obtains f g
where "h = f ∥ g"
proof
show "h = fst ∘ h ∥ snd ∘ h" by simp
qed

abbreviation "None_None ≡ (None, None)"
abbreviation "None_Some ≡ λ (y). (None, Some y)"
abbreviation "Some_None ≡ λ (x). (Some x, None)"
abbreviation "Some_Some ≡ λ (x, y). (Some x, Some y)"

abbreviation "None_None_None ≡ (None, None, None)"
abbreviation "None_None_Some ≡ λ (z). (None, None, Some z)"
abbreviation "None_Some_None ≡ λ (y). (None, Some y, None)"
abbreviation "None_Some_Some ≡ λ (y, z). (None, Some y, Some z)"
abbreviation "Some_None_None ≡ λ (x). (Some x, None, None)"
abbreviation "Some_None_Some ≡ λ (x, z). (Some x, None, Some z)"
abbreviation "Some_Some_None ≡ λ (x, y). (Some x, Some y, None)"
abbreviation "Some_Some_Some ≡ λ (x, y, z). (Some x, Some y, Some z)"

lemma inj_Some2[simp, intro]:
"inj None_Some"
"inj Some_None"
"inj Some_Some"
by (rule injI, force)+

lemma inj_Some3[simp, intro]:
"inj None_None_Some"
"inj None_Some_None"
"inj None_Some_Some"
"inj Some_None_None"
"inj Some_None_Some"
"inj Some_Some_None"
"inj Some_Some_Some"
by (rule injI, force)+

definition swap :: "'a × 'b ⇒ 'b × 'a"
where "swap x ≡ (snd x, fst x)"

lemma swap_simps[simp]: "swap (a, b) = (b, a)" unfolding swap_def by simp
lemma swap_inj[intro, simp]: "inj swap" by (rule injI, auto)
lemma swap_surj[intro, simp]: "surj swap" by (rule surjI[where ?f = swap], auto)
lemma swap_bij[intro, simp]: "bij swap" by (rule bijI, auto)

definition push :: "('a × 'b) × 'c ⇒ 'a × 'b × 'c"
where "push x ≡ (fst (fst x), snd (fst x), snd x)"
definition pull :: "'a × 'b × 'c ⇒ ('a × 'b) × 'c"
where "pull x ≡ ((fst x, fst (snd x)), snd (snd x))"

lemma push_simps[simp]: "push ((x, y), z) = (x, y, z)" unfolding push_def by simp
lemma pull_simps[simp]: "pull (x, y, z) = ((x, y), z)" unfolding pull_def by simp

definition label :: "'vertex × 'label × 'vertex ⇒ 'label"
where "label ≡ fst ∘ snd"

lemma label_select[simp]: "label (p, a, q) = a" unfolding label_def by simp

subsection ‹Theorems for @term{curry} and @term{split}›

lemma curry_split[simp]: "curry ∘ case_prod = id" by auto
lemma split_curry[simp]: "case_prod ∘ curry = id" by auto

lemma curry_le[simp]: "curry f ≤ curry g ⟷ f ≤ g" unfolding le_fun_def by force
lemma split_le[simp]: "case_prod f ≤ case_prod g ⟷ f ≤ g" unfolding le_fun_def by force

lemma mono_curry_left[simp]: "mono (curry ∘ h) ⟷ mono h"
unfolding mono_def by fastforce
lemma mono_split_left[simp]: "mono (case_prod ∘ h) ⟷ mono h"
unfolding mono_def by fastforce
lemma mono_curry_right[simp]: "mono (h ∘ curry) ⟷ mono h"
unfolding mono_def split_le[symmetric] by bestsimp
lemma mono_split_right[simp]: "mono (h ∘ case_prod) ⟷ mono h"
unfolding mono_def curry_le[symmetric] by bestsimp

lemma Collect_curry[simp]: "{x. P (curry x)} = case_prod ` {x. P x}" using image_Collect by fastforce
lemma Collect_split[simp]: "{x. P (case_prod x)} = curry ` {x. P x}" using image_Collect by force

lemma gfp_split_curry[simp]: "gfp (case_prod ∘ f ∘ curry) = case_prod (gfp f)"
proof -
have "gfp (case_prod ∘ f ∘ curry) = Sup {u. u ≤ case_prod (f (curry u))}" unfolding gfp_def by simp
also have "… = Sup {u. curry u ≤ curry (case_prod (f (curry u)))}" unfolding curry_le by simp
also have "… = Sup {u. curry u ≤ f (curry u)}" by simp
also have "… = Sup (case_prod ` {u. u ≤ f u})" unfolding Collect_curry[of "λ u. u ≤ f u"] by simp
also have "… = case_prod (Sup {u. u ≤ f u})" by (force simp add: image_comp)
also have "… = case_prod (gfp f)" unfolding gfp_def by simp
finally show ?thesis by this
qed
lemma gfp_curry_split[simp]: "gfp (curry ∘ f ∘ case_prod) = curry (gfp f)"
proof -
have "gfp (curry ∘ f ∘ case_prod) = Sup {u. u ≤ curry (f (case_prod u))}" unfolding gfp_def by simp
also have "… = Sup {u. case_prod u ≤ case_prod (curry (f (case_prod u)))}" unfolding split_le by simp
also have "… = Sup {u. case_prod u ≤ f (case_prod u)}" by simp
also have "… = Sup (curry ` {u. u ≤ f u})" unfolding Collect_split[of "λ u. u ≤ f u"] by simp
also have "… = curry (Sup {u. u ≤ f u})" by (force simp add: image_comp)
also have "… = curry (gfp f)" unfolding gfp_def by simp
finally show ?thesis by this
qed

lemma not_someI:
assumes "⋀ x. P x ⟹ False"
shows "¬ P (SOME x. P x)"
using assms by blast
lemma some_ccontr:
assumes "(⋀ x. ¬ P x) ⟹ False"
shows "P (SOME x. P x)"
using assms someI_ex ccontr by metis

end```