# Theory Group_Closure

```(*  Title:      HOL/Computational_Algebra/Group_Closure.thy
Author:     Johannes Hoelzl, TU Muenchen
Author:     Florian Haftmann, TU Muenchen
*)

theory Group_Closure
imports
Main
begin

begin

inductive_set group_closure :: "'a set ⇒ 'a set" for S
where base: "s ∈ insert 0 S ⟹ s ∈ group_closure S"
| diff: "s ∈ group_closure S ⟹ t ∈ group_closure S ⟹ s - t ∈ group_closure S"

lemma zero_in_group_closure [simp]:
"0 ∈ group_closure S"
using group_closure.base [of 0 S] by simp

lemma group_closure_minus_iff [simp]:
"- s ∈ group_closure S ⟷ s ∈ group_closure S"
using group_closure.diff [of 0 S s] group_closure.diff [of 0 S "- s"] by auto

"s + t ∈ group_closure S" if "s ∈ group_closure S" and "t ∈ group_closure S"
using that group_closure.diff [of s S "- t"] by auto

lemma group_closure_empty [simp]:
"group_closure {} = {0}"
by (rule ccontr) (auto elim: group_closure.induct)

lemma group_closure_insert_zero [simp]:
"group_closure (insert 0 S) = group_closure S"
by (auto elim: group_closure.induct intro: group_closure.intros)

end

context comm_ring_1
begin

lemma group_closure_scalar_mult_left:
"of_nat n * s ∈ group_closure S" if "s ∈ group_closure S"

lemma group_closure_scalar_mult_right:
"s * of_nat n ∈ group_closure S" if "s ∈ group_closure S"
using that group_closure_scalar_mult_left [of s S n] by (simp add: ac_simps)

end

lemma group_closure_abs_iff [simp]:
"¦s¦ ∈ group_closure S ⟷ s ∈ group_closure S" for s :: int

lemma group_closure_mult_left:
"s * t ∈ group_closure S" if "s ∈ group_closure S" for s t :: int
proof -
from that group_closure_scalar_mult_right [of s S "nat ¦t¦"]
have "s * int (nat ¦t¦) ∈ group_closure S"
by (simp only:)
then show ?thesis
by (cases "t ≥ 0") simp_all
qed

lemma group_closure_mult_right:
"s * t ∈ group_closure S" if "t ∈ group_closure S" for s t :: int
using that group_closure_mult_left [of t S s] by (simp add: ac_simps)

context idom
begin

lemma group_closure_mult_all_eq:
"group_closure (times k ` S) = times k ` group_closure S"
proof (rule; rule)
fix s
have *: "k * a + k * b = k * (a + b)"
"k * a - k * b = k * (a - b)" for a b
assume "s ∈ group_closure (times k ` S)"
then show "s ∈ times k ` group_closure S"
by induction (auto simp add: * image_iff intro: group_closure.base group_closure.diff bexI [of _ 0])
next
fix s
assume "s ∈ times k ` group_closure S"
then obtain r where r: "r ∈ group_closure S" and s: "s = k * r"
by auto
from r have "k * r ∈ group_closure (times k ` S)"
by (induction arbitrary: s) (auto simp add: algebra_simps intro: group_closure.intros)
with s show "s ∈ group_closure (times k ` S)"
by simp
qed

end

lemma Gcd_group_closure_eq_Gcd:
"Gcd (group_closure S) = Gcd S" for S :: "int set"
proof (rule associated_eqI)
have "Gcd S dvd s" if "s ∈ group_closure S" for s
using that by induction auto
then show "Gcd S dvd Gcd (group_closure S)"
by auto
have "Gcd (group_closure S) dvd s" if "s ∈ S" for s
proof -
from that have "s ∈ group_closure S"
then show ?thesis
by (rule Gcd_dvd)
qed
then show "Gcd (group_closure S) dvd Gcd S"
by auto
qed simp_all

lemma group_closure_sum:
fixes S :: "int set"
assumes X: "finite X" "X ≠ {}" "X ⊆ S"
shows "(∑x∈X. a x * x) ∈ group_closure S"
using X by (induction X rule: finite_ne_induct)

lemma Gcd_group_closure_in_group_closure:
"Gcd (group_closure S) ∈ group_closure S" for S :: "int set"
proof (cases "S ⊆ {0}")
case True
then have "S = {} ∨ S = {0}"
by auto
then show ?thesis
by auto
next
case False
then obtain s where s: "s ≠ 0" "s ∈ S"
by auto
then have s': "¦s¦ ≠ 0" "¦s¦ ∈ group_closure S"
by (auto intro: group_closure.base)
define m where "m = (LEAST n. n > 0 ∧ int n ∈ group_closure S)"
have "m > 0 ∧ int m ∈ group_closure S"
unfolding m_def
apply (rule LeastI [of _ "nat ¦s¦"])
using s'
by simp
then have m: "int m ∈ group_closure S" and "0 < m"
by auto

have "Gcd (group_closure S) = int m"
proof (rule associated_eqI)
from m show "Gcd (group_closure S) dvd int m"
by (rule Gcd_dvd)
show "int m dvd Gcd (group_closure S)"
proof (rule Gcd_greatest)
fix s
assume s: "s ∈ group_closure S"
show "int m dvd s"
proof (rule ccontr)
assume "¬ int m dvd s"
then have *: "0 < s mod int m"
using ‹0 < m› le_less by fastforce
have "m ≤ nat (s mod int m)"
proof (subst m_def, rule Least_le, rule)
from * show "0 < nat (s mod int m)"
by simp
from minus_div_mult_eq_mod [symmetric, of s "int m"]
have "s mod int m = s - s div int m * int m"
by auto
also have "s - s div int m * int m ∈ group_closure S"
by (auto intro: group_closure.diff s group_closure_mult_right m)
finally  show "int (nat (s mod int m)) ∈ group_closure S"
by simp
qed
with * have "int m ≤ s mod int m"
by simp
moreover have "s mod int m < int m"
using ‹0 < m› by simp
ultimately show False
by auto
qed
qed
qed simp_all
with m show ?thesis
by simp
qed

lemma Gcd_in_group_closure:
"Gcd S ∈ group_closure S" for S :: "int set"
using Gcd_group_closure_in_group_closure [of S]

lemma group_closure_eq:
"group_closure S = range (times (Gcd S))" for S :: "int set"
proof (auto intro: Gcd_in_group_closure group_closure_mult_left)
fix s
assume "s ∈ group_closure S"
then show "s ∈ range (times (Gcd S))"
proof induction
case (base s)
then have "Gcd S dvd s"
by (auto intro: Gcd_dvd)
then obtain t where "s = Gcd S * t" ..
then show ?case
by auto
next
case (diff s t)
moreover have "Gcd S * a - Gcd S * b = Gcd S * (a - b)" for a b