Theory Idempotent

Up to index of Isabelle/HOL/Constructor

theory Idempotent
imports Main
begin

header {* Idempotents *}

theory Idempotent
imports Main
begin

subsection {* Definition and basic properties *}

constdefs
  idempotent :: "('a => 'a) => bool"
  "idempotent p ≡ ∀x. p (p x) = p x"

lemma idempotent: "idempotent p ==> p (p x) = p x"
by (simp add: idempotent_def)

lemma idempotent_id: "idempotent id"
by (simp add: idempotent_def)

lemma idempotent_const: "idempotent (λx. c)"
by (simp add: idempotent_def)

lemma idempotent_functor:
assumes F2: "!!f g xs. m f (m g xs) = m (λx. f (g x)) xs"
shows "idempotent p ==> idempotent (m p)"
by (simp add: idempotent_def F2)

text {*
  The composition of two idempotents is equal to
  the lesser of the two (if they are comparable).
*}

lemma idempotent_less_comp1:
  "[|idempotent f; idempotent g; range f ⊆ range g|] ==> f (g x) = f x"
oops (* true for projections, but not for idempotents in general *)

lemma idempotent_less_comp2:
  "[|idempotent f; idempotent g; range f ⊆ range g|] ==> g (f x) = f x"
apply (subgoal_tac "f x ∈ range g")
apply clarify
apply (simp add: idempotent_def)
apply (erule subsetD)
apply simp
done


subsection {* Composing idempotents *}

lemma idempotent_fun:
  "[|idempotent p1; idempotent p2|]
    ==> idempotent (λf. p2 o f o p1)"
by (simp add: idempotent_def expand_fun_eq)

lemma idempotent_prod:
  "[|idempotent p1; idempotent p2|]
    ==> idempotent (λ(x,y). (p1 x, p2 y))"
by (simp add: idempotent_def)

lemma idempotent_sum:
  "[|idempotent p1; idempotent p2|]
    ==> idempotent (sum_case (Inl o p1) (Inr o p2))"
by (simp add: idempotent_def split: sum.split)


subsection {* A type of idempotents *}

typedef (open) 'a idem = "{p::'a => 'a. idempotent p}"
by (rule exI, auto intro: idempotent_id)

subsection {* Operations on idempotents *}

subsubsection {* Casting values into an idempotent *}

constdefs
  cast :: "'a idem => 'a => 'a"
  "cast ≡ Rep_idem"

lemma idempotent_cast: "idempotent (cast A)"
by (simp add: cast_def Rep_idem [simplified])

lemma Abs_idem_cast: "Abs_idem (cast A) = A"
by (simp add: cast_def Rep_idem_inverse)

lemma cast_Abs_idem: "idempotent f ==> cast (Abs_idem f) = f"
by (simp add: cast_def Abs_idem_inverse)

lemma cast_idem [simp]: "cast A (cast A x) = cast A x"
by (simp add: idempotent_cast idempotent)

lemma cast_idem2 [simp]: "cast A o cast A = cast A"
by (rule ext, simp)

lemma idempotent_equality: "cast A = cast B ==> A = B"
by (simp add: cast_def Rep_idem_inject)

subsubsection {* Ordering of idempotents *}

instance idem :: (type) ord ..
defs (overloaded)
  le_idem_def:
    "A ≤ B ≡ range (cast A) ⊆ range (cast B)"
(* not antisymmetric! *)

lemma idem_le_refl [simp, intro!]: "(A::'a idem) ≤ A"
by (simp add: le_idem_def)

subsubsection {* Membership in a idempotent *}

constdefs
  in_idem :: "'a => 'a idem => bool" (infixl ":::" 50)
  "x ::: A ≡ cast A x = x"

lemma in_idemI: "cast A x = x ==> x ::: A"
by (simp add: in_idem_def)

lemma in_idemD: "x ::: A ==> ∃y. x = cast A y"
by (unfold in_idem_def, rule exI, erule sym)

lemma in_idemE: "[|x ::: A; !!y. x = cast A y ==> R|] ==> R"
by (drule in_idemD, auto)

lemma cast_in_idem [simp]: "cast A x ::: A"
by (simp add: in_idemI)

lemma cast_fixed: "x ::: A ==> cast A x = x"
by (simp only: in_idem_def)

lemma subidemD: "[|A ≤ B; x ::: A|] ==> x ::: B"
 apply (unfold in_idem_def)
 apply (unfold le_idem_def)
 apply (subgoal_tac "x ∈ range (cast B)")
  apply clarsimp
 apply (erule subsetD)
 apply (erule subst)
 apply simp
done

lemma rev_subidemD: "[|x ::: A; A ≤ B|] ==> x ::: B"
by (rule subidemD)

lemma subidemI: "[|!!x. x ::: A ==> x ::: B|] ==> A ≤ B"
 apply atomize
 apply (simp add: le_idem_def)
 apply (rule subsetI)
 apply (drule_tac x=x in spec)
 apply clarsimp
 apply (simp add: in_idem_def)
 apply (erule subst, simp)
done

lemma nonempty_idem: "∃x. x ::: A"
 apply (unfold in_idem_def)
 apply (rule_tac x="cast A x" in exI)
 apply simp
done


subsubsection {* The identity idempotent *}

lemma cast_id_idem [simp]: "cast (Abs_idem id) = id"
by (simp add: cast_Abs_idem idempotent_id)

lemma in_idem_id_idem [simp, intro]: "x ::: Abs_idem id"
by (simp add: in_idemI)

lemma less_id_idemp [simp, intro]: "A ≤ Abs_idem id"
by (simp add: subidemI)

end

Definition and basic properties

lemma idempotent:

  idempotent p ==> p (p x) = p x

lemma idempotent_id:

  idempotent id

lemma idempotent_const:

  idempotent (λx. c)

lemma idempotent_functor:

  [| !!f g xs. m f (m g xs) = mx. f (g x)) xs; idempotent p |]
  ==> idempotent (m p)

lemma idempotent_less_comp2:

  [| idempotent f; idempotent g; range f ⊆ range g |] ==> g (f x) = f x

Composing idempotents

lemma idempotent_fun:

  [| idempotent p1.0; idempotent p2.0 |] ==> idempotent (λf. p2.0 o f o p1.0)

lemma idempotent_prod:

  [| idempotent p1.0; idempotent p2.0 |]
  ==> idempotent (λ(x, y). (p1.0 x, p2.0 y))

lemma idempotent_sum:

  [| idempotent p1.0; idempotent p2.0 |]
  ==> idempotent (sum_case (Inl o p1.0) (Inr o p2.0))

A type of idempotents

Operations on idempotents

Casting values into an idempotent

lemma idempotent_cast:

  idempotent (cast A)

lemma Abs_idem_cast:

  Abs_idem (cast A) = A

lemma cast_Abs_idem:

  idempotent f ==> cast (Abs_idem f) = f

lemma cast_idem:

  cast A (cast A x) = cast A x

lemma cast_idem2:

  cast A o cast A = cast A

lemma idempotent_equality:

  cast A = cast B ==> A = B

Ordering of idempotents

lemma idem_le_refl:

  AA

Membership in a idempotent

lemma in_idemI:

  cast A x = x ==> x ::: A

lemma in_idemD:

  x ::: A ==> ∃y. x = cast A y

lemma in_idemE:

  [| x ::: A; !!y. x = cast A y ==> R |] ==> R

lemma cast_in_idem:

  cast A x ::: A

lemma cast_fixed:

  x ::: A ==> cast A x = x

lemma subidemD:

  [| AB; x ::: A |] ==> x ::: B

lemma rev_subidemD:

  [| x ::: A; AB |] ==> x ::: B

lemma subidemI:

  (!!x. x ::: A ==> x ::: B) ==> AB

lemma nonempty_idem:

x. x ::: A

The identity idempotent

lemma cast_id_idem:

  cast (Abs_idem id) = id

lemma in_idem_id_idem:

  x ::: Abs_idem id

lemma less_id_idemp:

  A ≤ Abs_idem id