l3lab/ntp-mathlib huggingface dataset:
theorem span_singleton_mul_left_inj [IsDomain R] {x : R} (hx : x ≠ 0) :
    I * span {x} = J * span {x} ↔ I = J := by
  

Proof state:
R : Type u
ι : Type u_1
inst✝¹ : CommSemiring R
I J K L : Ideal R
inst✝ : IsDomain R
x : R
hx : x ≠ 0
⊢ I * span {x} = J * span {x} ↔ I = J

Next tactic:
simp only [le_antisymm_iff, span_singleton_mul_left_mono hx]
theorem eq_span_singleton_mul {x : R} (I J : Ideal R) :
    I = span {x} * J ↔ (∀ zI ∈ I, ∃ zJ ∈ J, x * zJ = zI) ∧ ∀ z ∈ J, x * z ∈ I := by
  

Proof state:
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I✝ J✝ K L : Ideal R
x : R
I J : Ideal R
⊢ I = span {x} * J ↔ (∀ zI ∈ I, ∃ zJ ∈ J, x * zJ = zI) ∧ ∀ z ∈ J, x * z ∈ I

Next tactic:
simp only [le_antisymm_iff, le_span_singleton_mul_iff, span_singleton_mul_le_iff]
theorem span_singleton_mul_eq_span_singleton_mul {x y : R} (I J : Ideal R) :
    span {x} * I = span {y} * J ↔
      (∀ zI ∈ I, ∃ zJ ∈ J, x * zI = y * zJ) ∧ ∀ zJ ∈ J, ∃ zI ∈ I, x * zI = y * zJ :=
  by 

Proof state:
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I✝ J✝ K L : Ideal R
x y : R
I J : Ideal R
⊢ span {x} * I = span {y} * J ↔ (∀ zI ∈ I, ∃ zJ ∈ J, x * zI = y * zJ) ∧ ∀ zJ ∈ J, ∃ zI ∈ I, x * zI = y * zJ

Next tactic:
simp only [le_antisymm_iff, span_singleton_mul_le_span_singleton_mul, eq_comm]
@[simp]
theorem multiset_prod_span_singleton (m : Multiset R) :
    (m.map fun x => Ideal.span {x}).prod = Ideal.span ({Multiset.prod m} : Set R) :=
  Multiset.induction_on m (by 

Proof state:
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
m : Multiset R
⊢ Multiset.prod (Multiset.map (fun x => span {x}) 0) = span {Multiset.prod 0}

Next tactic:
simp
@[simp]
theorem multiset_prod_span_singleton (m : Multiset R) :
    (m.map fun x => Ideal.span {x}).prod = Ideal.span ({Multiset.prod m} : Set R) :=
  Multiset.induction_on m (by simp) fun a m ih => by
    

Proof state:
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
m✝ : Multiset R
a : R
m : Multiset R
ih : Multiset.prod (Multiset.map (fun x => span {x}) m) = span {Multiset.prod m}
⊢ Multiset.prod (Multiset.map (fun x => span {x}) (a ::ₘ m)) = span {Multiset.prod (a ::ₘ m)}

Next tactic:
simp only [Multiset.map_cons, Multiset.prod_cons, ih, ← Ideal.span_singleton_mul_span_singleton]
theorem finset_inf_span_singleton {ι : Type*} (s : Finset ι) (I : ι → R)
    (hI : Set.Pairwise (↑s) (IsCoprime on I)) :
    (s.inf fun i => Ideal.span ({I i} : Set R)) = Ideal.span {∏ i in s, I i} := by
  

Proof state:
R : Type u
ι✝ : Type u_1
inst✝ : CommSemiring R
I✝ J K L : Ideal R
ι : Type u_2
s : Finset ι
I : ι → R
hI : Set.Pairwise (↑s) (IsCoprime on I)
⊢ (Finset.inf s fun i => span {I i}) = span {∏ i in s, I i}

Next tactic:
ext x
theorem finset_inf_span_singleton {ι : Type*} (s : Finset ι) (I : ι → R)
    (hI : Set.Pairwise (↑s) (IsCoprime on I)) :
    (s.inf fun i => Ideal.span ({I i} : Set R)) = Ideal.span {∏ i in s, I i} := by
  ext x
  

Proof state:
case h
R : Type u
ι✝ : Type u_1
inst✝ : CommSemiring R
I✝ J K L : Ideal R
ι : Type u_2
s : Finset ι
I : ι → R
hI : Set.Pairwise (↑s) (IsCoprime on I)
x : R
⊢ (x ∈ Finset.inf s fun i => span {I i}) ↔ x ∈ span {∏ i in s, I i}

Next tactic:
simp only [Submodule.mem_finset_inf, Ideal.mem_span_singleton]
theorem finset_inf_span_singleton {ι : Type*} (s : Finset ι) (I : ι → R)
    (hI : Set.Pairwise (↑s) (IsCoprime on I)) :
    (s.inf fun i => Ideal.span ({I i} : Set R)) = Ideal.span {∏ i in s, I i} := by
  ext x
  simp only [Submodule.mem_finset_inf, Ideal.mem_span_singleton]
  

Proof state:
case h
R : Type u
ι✝ : Type u_1
inst✝ : CommSemiring R
I✝ J K L : Ideal R
ι : Type u_2
s : Finset ι
I : ι → R
hI : Set.Pairwise (↑s) (IsCoprime on I)
x : R
⊢ (∀ i ∈ s, I i ∣ x) ↔ ∏ i in s, I i ∣ x

Next tactic:
exact ⟨Finset.prod_dvd_of_coprime hI, fun h i hi => (Finset.dvd_prod_of_mem _ hi).trans h⟩
theorem iInf_span_singleton {ι : Type*} [Fintype ι] {I : ι → R}
    (hI : ∀ (i j) (_ : i ≠ j), IsCoprime (I i) (I j)) :
    ⨅ i, span ({I i} : Set R) = span {∏ i, I i} := by
  

Proof state:
R : Type u
ι✝ : Type u_1
inst✝¹ : CommSemiring R
I✝ J K L : Ideal R
ι : Type u_2
inst✝ : Fintype ι
I : ι → R
hI : ∀ (i j : ι), i ≠ j → IsCoprime (I i) (I j)
⊢ ⨅ i, span {I i} = span {∏ i : ι, I i}

Next tactic:
rw [← Finset.inf_univ_eq_iInf, finset_inf_span_singleton]
theorem iInf_span_singleton {ι : Type*} [Fintype ι] {I : ι → R}
    (hI : ∀ (i j) (_ : i ≠ j), IsCoprime (I i) (I j)) :
    ⨅ i, span ({I i} : Set R) = span {∏ i, I i} := by
  rw [← Finset.inf_univ_eq_iInf, finset_inf_span_singleton]
  

Proof state:
case hI
R : Type u
ι✝ : Type u_1
inst✝¹ : CommSemiring R
I✝ J K L : Ideal R
ι : Type u_2
inst✝ : Fintype ι
I : ι → R
hI : ∀ (i j : ι), i ≠ j → IsCoprime (I i) (I j)
⊢ Set.Pairwise (↑Finset.univ) (IsCoprime on fun i => I i)

Next tactic:
rwa [Finset.coe_univ, Set.pairwise_univ]
theorem iInf_span_singleton_natCast {R : Type*} [CommRing R] {ι : Type*} [Fintype ι]
    {I : ι → ℕ} (hI : ∀ (i j : ι), i ≠ j → (I i).Coprime (I j)) :
    ⨅ (i : ι), span {(I i : R)} = span {((∏ i : ι, I i : ℕ) : R)} := by
  

Proof state:
R✝ : Type u
ι✝ : Type u_1
inst✝² : CommSemiring R✝
I✝ J K L : Ideal R✝
R : Type u_2
inst✝¹ : CommRing R
ι : Type u_3
inst✝ : Fintype ι
I : ι → ℕ
hI : ∀ (i j : ι), i ≠ j → Nat.Coprime (I i) (I j)
⊢ ⨅ i, span {↑(I i)} = span {↑(∏ i : ι, I i)}

Next tactic:
rw [iInf_span_singleton, Nat.cast_prod]
theorem iInf_span_singleton_natCast {R : Type*} [CommRing R] {ι : Type*} [Fintype ι]
    {I : ι → ℕ} (hI : ∀ (i j : ι), i ≠ j → (I i).Coprime (I j)) :
    ⨅ (i : ι), span {(I i : R)} = span {((∏ i : ι, I i : ℕ) : R)} := by
  rw [iInf_span_singleton, Nat.cast_prod]
  

Proof state:
R✝ : Type u
ι✝ : Type u_1
inst✝² : CommSemiring R✝
I✝ J K L : Ideal R✝
R : Type u_2
inst✝¹ : CommRing R
ι : Type u_3
inst✝ : Fintype ι
I : ι → ℕ
hI : ∀ (i j : ι), i ≠ j → Nat.Coprime (I i) (I j)
⊢ ∀ (i j : ι), i ≠ j → IsCoprime ↑(I i) ↑(I j)

Next tactic:
exact fun i j h ↦ (hI i j h).cast
theorem sup_eq_top_iff_isCoprime {R : Type*} [CommSemiring R] (x y : R) :
    span ({x} : Set R) ⊔ span {y} = ⊤ ↔ IsCoprime x y := by
  

Proof state:
R✝ : Type u
ι : Type u_1
inst✝¹ : CommSemiring R✝
I J K L : Ideal R✝
R : Type u_2
inst✝ : CommSemiring R
x y : R
⊢ span {x} ⊔ span {y} = ⊤ ↔ IsCoprime x y

Next tactic:
rw [eq_top_iff_one, Submodule.mem_sup]
theorem sup_eq_top_iff_isCoprime {R : Type*} [CommSemiring R] (x y : R) :
    span ({x} : Set R) ⊔ span {y} = ⊤ ↔ IsCoprime x y := by
  rw [eq_top_iff_one, Submodule.mem_sup]
  

Proof state:
R✝ : Type u
ι : Type u_1
inst✝¹ : CommSemiring R✝
I J K L : Ideal R✝
R : Type u_2
inst✝ : CommSemiring R
x y : R
⊢ (∃ y_1 ∈ span {x}, ∃ z ∈ span {y}, y_1 + z = 1) ↔ IsCoprime x y

Next tactic:
constructor
theorem sup_eq_top_iff_isCoprime {R : Type*} [CommSemiring R] (x y : R) :
    span ({x} : Set R) ⊔ span {y} = ⊤ ↔ IsCoprime x y := by
  rw [eq_top_iff_one, Submodule.mem_sup]
  constructor
  · 

Proof state:
case mp
R✝ : Type u
ι : Type u_1
inst✝¹ : CommSemiring R✝
I J K L : Ideal R✝
R : Type u_2
inst✝ : CommSemiring R
x y : R
⊢ (∃ y_1 ∈ span {x}, ∃ z ∈ span {y}, y_1 + z = 1) → IsCoprime x y

Next tactic:
rintro ⟨u, hu, v, hv, h1⟩
theorem sup_eq_top_iff_isCoprime {R : Type*} [CommSemiring R] (x y : R) :
    span ({x} : Set R) ⊔ span {y} = ⊤ ↔ IsCoprime x y := by
  rw [eq_top_iff_one, Submodule.mem_sup]
  constructor
  · rintro ⟨u, hu, v, hv, h1⟩
    

Proof state:
case mp.intro.intro.intro.intro
R✝ : Type u
ι : Type u_1
inst✝¹ : CommSemiring R✝
I J K L : Ideal R✝
R : Type u_2
inst✝ : CommSemiring R
x y u : R
hu : u ∈ span {x}
v : R
hv : v ∈ span {y}
h1 : u + v = 1
⊢ IsCoprime x y

Next tactic:
rw [mem_span_singleton'] at hu hv
theorem sup_eq_top_iff_isCoprime {R : Type*} [CommSemiring R] (x y : R) :
    span ({x} : Set R) ⊔ span {y} = ⊤ ↔ IsCoprime x y := by
  rw [eq_top_iff_one, Submodule.mem_sup]
  constructor
  · rintro ⟨u, hu, v, hv, h1⟩
    rw [mem_span_singleton'] at hu hv
    

Proof state:
case mp.intro.intro.intro.intro
R✝ : Type u
ι : Type u_1
inst✝¹ : CommSemiring R✝
I J K L : Ideal R✝
R : Type u_2
inst✝ : CommSemiring R
x y u : R
hu : ∃ a, a * x = u
v : R
hv : ∃ a, a * y = v
h1 : u + v = 1
⊢ IsCoprime x y

Next tactic:
rw [← hu.choose_spec, ← hv.choose_spec] at h1
theorem sup_eq_top_iff_isCoprime {R : Type*} [CommSemiring R] (x y : R) :
    span ({x} : Set R) ⊔ span {y} = ⊤ ↔ IsCoprime x y := by
  rw [eq_top_iff_one, Submodule.mem_sup]
  constructor
  · rintro ⟨u, hu, v, hv, h1⟩
    rw [mem_span_singleton'] at hu hv
    rw [← hu.choose_spec, ← hv.choose_spec] at h1
    

Proof state:
case mp.intro.intro.intro.intro
R✝ : Type u
ι : Type u_1
inst✝¹ : CommSemiring R✝
I J K L : Ideal R✝
R : Type u_2
inst✝ : CommSemiring R
x y u : R
hu : ∃ a, a * x = u
v : R
hv : ∃ a, a * y = v
h1 : Exists.choose hu * x + Exists.choose hv * y = 1
⊢ IsCoprime x y

Next tactic:
exact ⟨_, _, h1⟩
theorem sup_eq_top_iff_isCoprime {R : Type*} [CommSemiring R] (x y : R) :
    span ({x} : Set R) ⊔ span {y} = ⊤ ↔ IsCoprime x y := by
  rw [eq_top_iff_one, Submodule.mem_sup]
  constructor
  · rintro ⟨u, hu, v, hv, h1⟩
    rw [mem_span_singleton'] at hu hv
    rw [← hu.choose_spec, ← hv.choose_spec] at h1
    exact ⟨_, _, h1⟩
  · 

Proof state:
case mpr
R✝ : Type u
ι : Type u_1
inst✝¹ : CommSemiring R✝
I J K L : Ideal R✝
R : Type u_2
inst✝ : CommSemiring R
x y : R
⊢ IsCoprime x y → ∃ y_1 ∈ span {x}, ∃ z ∈ span {y}, y_1 + z = 1

Next tactic:
exact fun ⟨u, v, h1⟩ =>
      ⟨_, mem_span_singleton'.mpr ⟨_, rfl⟩, _, mem_span_singleton'.mpr ⟨_, rfl⟩, h1⟩
theorem multiset_prod_le_inf {s : Multiset (Ideal R)} : s.prod ≤ s.inf := by
  

Proof state:
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
s : Multiset (Ideal R)
⊢ Multiset.prod s ≤ Multiset.inf s

Next tactic:
classical
    refine' s.induction_on _ _
    · rw [Multiset.inf_zero]
      exact le_top
    intro a s ih
    rw [Multiset.prod_cons, Multiset.inf_cons]
    exact le_trans mul_le_inf (inf_le_inf le_rfl ih)
theorem multiset_prod_le_inf {s : Multiset (Ideal R)} : s.prod ≤ s.inf := by
  classical
    

Proof state:
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
s : Multiset (Ideal R)
⊢ Multiset.prod s ≤ Multiset.inf s

Next tactic:
refine' s.induction_on _ _
theorem multiset_prod_le_inf {s : Multiset (Ideal R)} : s.prod ≤ s.inf := by
  classical
    refine' s.induction_on _ _
    · 

Proof state:
case refine'_1
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
s : Multiset (Ideal R)
⊢ Multiset.prod 0 ≤ Multiset.inf 0

Next tactic:
rw [Multiset.inf_zero]
theorem multiset_prod_le_inf {s : Multiset (Ideal R)} : s.prod ≤ s.inf := by
  classical
    refine' s.induction_on _ _
    · rw [Multiset.inf_zero]
      

Proof state:
case refine'_1
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
s : Multiset (Ideal R)
⊢ Multiset.prod 0 ≤ ⊤

Next tactic:
exact le_top
theorem multiset_prod_le_inf {s : Multiset (Ideal R)} : s.prod ≤ s.inf := by
  classical
    refine' s.induction_on _ _
    · rw [Multiset.inf_zero]
      exact le_top
    

Proof state:
case refine'_2
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
s : Multiset (Ideal R)
⊢ ∀ ⦃a : Ideal R⦄ {s : Multiset (Ideal R)},
    Multiset.prod s ≤ Multiset.inf s → Multiset.prod (a ::ₘ s) ≤ Multiset.inf (a ::ₘ s)

Next tactic:
intro a s ih
theorem multiset_prod_le_inf {s : Multiset (Ideal R)} : s.prod ≤ s.inf := by
  classical
    refine' s.induction_on _ _
    · rw [Multiset.inf_zero]
      exact le_top
    intro a s ih
    

Proof state:
case refine'_2
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
s✝ : Multiset (Ideal R)
a : Ideal R
s : Multiset (Ideal R)
ih : Multiset.prod s ≤ Multiset.inf s
⊢ Multiset.prod (a ::ₘ s) ≤ Multiset.inf (a ::ₘ s)

Next tactic:
rw [Multiset.prod_cons, Multiset.inf_cons]
theorem multiset_prod_le_inf {s : Multiset (Ideal R)} : s.prod ≤ s.inf := by
  classical
    refine' s.induction_on _ _
    · rw [Multiset.inf_zero]
      exact le_top
    intro a s ih
    rw [Multiset.prod_cons, Multiset.inf_cons]
    

Proof state:
case refine'_2
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
s✝ : Multiset (Ideal R)
a : Ideal R
s : Multiset (Ideal R)
ih : Multiset.prod s ≤ Multiset.inf s
⊢ a * Multiset.prod s ≤ a ⊓ Multiset.inf s

Next tactic:
exact le_trans mul_le_inf (inf_le_inf le_rfl ih)
theorem sup_mul_eq_of_coprime_left (h : I ⊔ J = ⊤) : I ⊔ J * K = I ⊔ K :=
  le_antisymm (sup_le_sup_left mul_le_left _) fun i hi => by
    

Proof state:
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
h : I ⊔ J = ⊤
i : R
hi : i ∈ I ⊔ K
⊢ i ∈ I ⊔ J * K

Next tactic:
rw [eq_top_iff_one] at h
theorem sup_mul_eq_of_coprime_left (h : I ⊔ J = ⊤) : I ⊔ J * K = I ⊔ K :=
  le_antisymm (sup_le_sup_left mul_le_left _) fun i hi => by
    rw [eq_top_iff_one] at h; 

Proof state:
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
h : 1 ∈ I ⊔ J
i : R
hi : i ∈ I ⊔ K
⊢ i ∈ I ⊔ J * K

Next tactic:
rw [Submodule.mem_sup] at h hi ⊢
theorem sup_mul_eq_of_coprime_left (h : I ⊔ J = ⊤) : I ⊔ J * K = I ⊔ K :=
  le_antisymm (sup_le_sup_left mul_le_left _) fun i hi => by
    rw [eq_top_iff_one] at h; rw [Submodule.mem_sup] at h hi ⊢
    

Proof state:
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
h : ∃ y ∈ I, ∃ z ∈ J, y + z = 1
i : R
hi : ∃ y ∈ I, ∃ z ∈ K, y + z = i
⊢ ∃ y ∈ I, ∃ z ∈ J * K, y + z = i

Next tactic:
obtain ⟨i1, hi1, j, hj, h⟩ := h
theorem sup_mul_eq_of_coprime_left (h : I ⊔ J = ⊤) : I ⊔ J * K = I ⊔ K :=
  le_antisymm (sup_le_sup_left mul_le_left _) fun i hi => by
    rw [eq_top_iff_one] at h; rw [Submodule.mem_sup] at h hi ⊢
    obtain ⟨i1, hi1, j, hj, h⟩ := h; 

Proof state:
case intro.intro.intro.intro
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
i : R
hi : ∃ y ∈ I, ∃ z ∈ K, y + z = i
i1 : R
hi1 : i1 ∈ I
j : R
hj : j ∈ J
h : i1 + j = 1
⊢ ∃ y ∈ I, ∃ z ∈ J * K, y + z = i

Next tactic:
obtain ⟨i', hi', k, hk, hi⟩ := hi
theorem sup_mul_eq_of_coprime_left (h : I ⊔ J = ⊤) : I ⊔ J * K = I ⊔ K :=
  le_antisymm (sup_le_sup_left mul_le_left _) fun i hi => by
    rw [eq_top_iff_one] at h; rw [Submodule.mem_sup] at h hi ⊢
    obtain ⟨i1, hi1, j, hj, h⟩ := h; obtain ⟨i', hi', k, hk, hi⟩ := hi
    

Proof state:
case intro.intro.intro.intro.intro.intro.intro.intro
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
i i1 : R
hi1 : i1 ∈ I
j : R
hj : j ∈ J
h : i1 + j = 1
i' : R
hi' : i' ∈ I
k : R
hk : k ∈ K
hi : i' + k = i
⊢ ∃ y ∈ I, ∃ z ∈ J * K, y + z = i

Next tactic:
refine' ⟨_, add_mem hi' (mul_mem_right k _ hi1), _, mul_mem_mul hj hk, _⟩
theorem sup_mul_eq_of_coprime_left (h : I ⊔ J = ⊤) : I ⊔ J * K = I ⊔ K :=
  le_antisymm (sup_le_sup_left mul_le_left _) fun i hi => by
    rw [eq_top_iff_one] at h; rw [Submodule.mem_sup] at h hi ⊢
    obtain ⟨i1, hi1, j, hj, h⟩ := h; obtain ⟨i', hi', k, hk, hi⟩ := hi
    refine' ⟨_, add_mem hi' (mul_mem_right k _ hi1), _, mul_mem_mul hj hk, _⟩
    

Proof state:
case intro.intro.intro.intro.intro.intro.intro.intro
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
i i1 : R
hi1 : i1 ∈ I
j : R
hj : j ∈ J
h : i1 + j = 1
i' : R
hi' : i' ∈ I
k : R
hk : k ∈ K
hi : i' + k = i
⊢ i' + i1 * k + j * k = i

Next tactic:
rw [add_assoc, ← add_mul, h, one_mul, hi]
theorem sup_mul_eq_of_coprime_right (h : I ⊔ K = ⊤) : I ⊔ J * K = I ⊔ J := by
  

Proof state:
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
h : I ⊔ K = ⊤
⊢ I ⊔ J * K = I ⊔ J

Next tactic:
rw [mul_comm]
theorem sup_mul_eq_of_coprime_right (h : I ⊔ K = ⊤) : I ⊔ J * K = I ⊔ J := by
  rw [mul_comm]
  

Proof state:
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
h : I ⊔ K = ⊤
⊢ I ⊔ K * J = I ⊔ J

Next tactic:
exact sup_mul_eq_of_coprime_left h
theorem mul_sup_eq_of_coprime_left (h : I ⊔ J = ⊤) : I * K ⊔ J = K ⊔ J := by
  

Proof state:
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
h : I ⊔ J = ⊤
⊢ I * K ⊔ J = K ⊔ J

Next tactic:
rw [sup_comm] at h
theorem mul_sup_eq_of_coprime_left (h : I ⊔ J = ⊤) : I * K ⊔ J = K ⊔ J := by
  rw [sup_comm] at h
  

Proof state:
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
h : J ⊔ I = ⊤
⊢ I * K ⊔ J = K ⊔ J

Next tactic:
rw [sup_comm, sup_mul_eq_of_coprime_left h, sup_comm]
theorem mul_sup_eq_of_coprime_right (h : K ⊔ J = ⊤) : I * K ⊔ J = I ⊔ J := by
  

Proof state:
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
h : K ⊔ J = ⊤
⊢ I * K ⊔ J = I ⊔ J

Next tactic:
rw [sup_comm] at h
theorem mul_sup_eq_of_coprime_right (h : K ⊔ J = ⊤) : I * K ⊔ J = I ⊔ J := by
  rw [sup_comm] at h
  

Proof state:
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
h : J ⊔ K = ⊤
⊢ I * K ⊔ J = I ⊔ J

Next tactic:
rw [sup_comm, sup_mul_eq_of_coprime_right h, sup_comm]
theorem sup_prod_eq_top {s : Finset ι} {J : ι → Ideal R} (h : ∀ i, i ∈ s → I ⊔ J i = ⊤) :
    (I ⊔ ∏ i in s, J i) = ⊤ :=
  Finset.prod_induction _ (fun J => I ⊔ J = ⊤)
    (fun J K hJ hK => (sup_mul_eq_of_coprime_left hJ).trans hK)
    (by 

Proof state:
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J✝ K L : Ideal R
s : Finset ι
J : ι → Ideal R
h : ∀ i ∈ s, I ⊔ J i = ⊤
⊢ (fun J => I ⊔ J = ⊤) 1

Next tactic:
simp_rw [one_eq_top, sup_top_eq]
theorem sup_pow_eq_top {n : ℕ} (h : I ⊔ J = ⊤) : I ⊔ J ^ n = ⊤ := by
  

Proof state:
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
n : ℕ
h : I ⊔ J = ⊤
⊢ I ⊔ J ^ n = ⊤

Next tactic:
rw [← Finset.card_range n, ← Finset.prod_const]
theorem sup_pow_eq_top {n : ℕ} (h : I ⊔ J = ⊤) : I ⊔ J ^ n = ⊤ := by
  rw [← Finset.card_range n, ← Finset.prod_const]
  

Proof state:
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
n : ℕ
h : I ⊔ J = ⊤
⊢ I ⊔ ∏ _x in Finset.range n, J = ⊤

Next tactic:
exact sup_prod_eq_top fun _ _ => h
theorem pow_sup_eq_top {n : ℕ} (h : I ⊔ J = ⊤) : I ^ n ⊔ J = ⊤ := by
  

Proof state:
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
n : ℕ
h : I ⊔ J = ⊤
⊢ I ^ n ⊔ J = ⊤

Next tactic:
rw [← Finset.card_range n, ← Finset.prod_const]
theorem pow_sup_eq_top {n : ℕ} (h : I ⊔ J = ⊤) : I ^ n ⊔ J = ⊤ := by
  rw [← Finset.card_range n, ← Finset.prod_const]
  

Proof state:
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
n : ℕ
h : I ⊔ J = ⊤
⊢ (∏ _x in Finset.range n, I) ⊔ J = ⊤

Next tactic:
exact prod_sup_eq_top fun _ _ => h
theorem mul_bot : I * ⊥ = ⊥ := by 

Proof state:
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
⊢ I * ⊥ = ⊥

Next tactic:
simp
theorem bot_mul : ⊥ * I = ⊥ := by 

Proof state:
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
⊢ ⊥ * I = ⊥

Next tactic:
simp
theorem pow_le_pow_right {m n : ℕ} (h : m ≤ n) : I ^ n ≤ I ^ m := by
  

Proof state:
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
m n : ℕ
h : m ≤ n
⊢ I ^ n ≤ I ^ m

Next tactic:
cases' Nat.exists_eq_add_of_le h with k hk
theorem pow_le_pow_right {m n : ℕ} (h : m ≤ n) : I ^ n ≤ I ^ m := by
  cases' Nat.exists_eq_add_of_le h with k hk
  

Proof state:
case intro
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
m n : ℕ
h : m ≤ n
k : ℕ
hk : n = m + k
⊢ I ^ n ≤ I ^ m

Next tactic:
rw [hk, pow_add]
theorem pow_le_pow_right {m n : ℕ} (h : m ≤ n) : I ^ n ≤ I ^ m := by
  cases' Nat.exists_eq_add_of_le h with k hk
  rw [hk, pow_add]
  

Proof state:
case intro
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
m n : ℕ
h : m ≤ n
k : ℕ
hk : n = m + k
⊢ I ^ m * I ^ k ≤ I ^ m

Next tactic:
exact le_trans mul_le_inf inf_le_left
theorem pow_right_mono {I J : Ideal R} (e : I ≤ J) (n : ℕ) : I ^ n ≤ J ^ n := by
  

Proof state:
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I✝ J✝ K L I J : Ideal R
e : I ≤ J
n : ℕ
⊢ I ^ n ≤ J ^ n

Next tactic:
induction' n with _ hn
theorem pow_right_mono {I J : Ideal R} (e : I ≤ J) (n : ℕ) : I ^ n ≤ J ^ n := by
  induction' n with _ hn
  · 

Proof state:
case zero
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I✝ J✝ K L I J : Ideal R
e : I ≤ J
⊢ I ^ Nat.zero ≤ J ^ Nat.zero

Next tactic:
rw [pow_zero, pow_zero]
theorem pow_right_mono {I J : Ideal R} (e : I ≤ J) (n : ℕ) : I ^ n ≤ J ^ n := by
  induction' n with _ hn
  · rw [pow_zero, pow_zero]
  · 

Proof state:
case succ
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I✝ J✝ K L I J : Ideal R
e : I ≤ J
n✝ : ℕ
hn : I ^ n✝ ≤ J ^ n✝
⊢ I ^ Nat.succ n✝ ≤ J ^ Nat.succ n✝

Next tactic:
rw [pow_succ, pow_succ]
theorem pow_right_mono {I J : Ideal R} (e : I ≤ J) (n : ℕ) : I ^ n ≤ J ^ n := by
  induction' n with _ hn
  · rw [pow_zero, pow_zero]
  · rw [pow_succ, pow_succ]
    

Proof state:
case succ
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I✝ J✝ K L I J : Ideal R
e : I ≤ J
n✝ : ℕ
hn : I ^ n✝ ≤ J ^ n✝
⊢ I * I ^ n✝ ≤ J * J ^ n✝

Next tactic:
exact Ideal.mul_mono e hn
theorem mul_eq_bot {R : Type*} [CommSemiring R] [NoZeroDivisors R] {I J : Ideal R} :
    I * J = ⊥ ↔ I = ⊥ ∨ J = ⊥ :=
  ⟨fun hij =>
    or_iff_not_imp_left.mpr fun I_ne_bot =>
      J.eq_bot_iff.mpr fun j hj =>
        let ⟨i, hi, ne0⟩ := I.ne_bot_iff.mp I_ne_bot
        Or.resolve_left (mul_eq_zero.mp ((I * J).eq_bot_iff.mp hij _ (mul_mem_mul hi hj))) ne0,
    fun h => by 

Proof state:
R✝ : Type u
ι : Type u_1
inst✝² : CommSemiring R✝
I✝ J✝ K L : Ideal R✝
R : Type u_2
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
I J : Ideal R
h : I = ⊥ ∨ J = ⊥
⊢ I * J = ⊥

Next tactic:
cases' h with h h
theorem mul_eq_bot {R : Type*} [CommSemiring R] [NoZeroDivisors R] {I J : Ideal R} :
    I * J = ⊥ ↔ I = ⊥ ∨ J = ⊥ :=
  ⟨fun hij =>
    or_iff_not_imp_left.mpr fun I_ne_bot =>
      J.eq_bot_iff.mpr fun j hj =>
        let ⟨i, hi, ne0⟩ := I.ne_bot_iff.mp I_ne_bot
        Or.resolve_left (mul_eq_zero.mp ((I * J).eq_bot_iff.mp hij _ (mul_mem_mul hi hj))) ne0,
    fun h => by cases' h with h h <;> 

Proof state:
case inl
R✝ : Type u
ι : Type u_1
inst✝² : CommSemiring R✝
I✝ J✝ K L : Ideal R✝
R : Type u_2
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
I J : Ideal R
h : I = ⊥
⊢ I * J = ⊥

Next tactic:
rw [← Ideal.mul_bot, h, Ideal.mul_comm]
theorem mul_eq_bot {R : Type*} [CommSemiring R] [NoZeroDivisors R] {I J : Ideal R} :
    I * J = ⊥ ↔ I = ⊥ ∨ J = ⊥ :=
  ⟨fun hij =>
    or_iff_not_imp_left.mpr fun I_ne_bot =>
      J.eq_bot_iff.mpr fun j hj =>
        let ⟨i, hi, ne0⟩ := I.ne_bot_iff.mp I_ne_bot
        Or.resolve_left (mul_eq_zero.mp ((I * J).eq_bot_iff.mp hij _ (mul_mem_mul hi hj))) ne0,
    fun h => by cases' h with h h <;> 

Proof state:
case inr
R✝ : Type u
ι : Type u_1
inst✝² : CommSemiring R✝
I✝ J✝ K L : Ideal R✝
R : Type u_2
inst✝¹ : CommSemiring R
inst✝ : NoZeroDivisors R
I J : Ideal R
h : J = ⊥
⊢ I * J = ⊥

Next tactic:
rw [← Ideal.mul_bot, h, Ideal.mul_comm]
/-- A product of ideals in an integral domain is zero if and only if one of the terms is zero. -/
theorem prod_eq_bot {R : Type*} [CommRing R] [IsDomain R] {s : Multiset (Ideal R)} :
    s.prod = ⊥ ↔ ∃ I ∈ s, I = ⊥ := by
  

Proof state:
R✝ : Type u
ι : Type u_1
inst✝² : CommSemiring R✝
I J K L : Ideal R✝
R : Type u_2
inst✝¹ : CommRing R
inst✝ : IsDomain R
s : Multiset (Ideal R)
⊢ Multiset.prod s = ⊥ ↔ ∃ I ∈ s, I = ⊥

Next tactic:
rw [bot_eq_zero, prod_zero_iff_exists_zero]
/-- A product of ideals in an integral domain is zero if and only if one of the terms is zero. -/
theorem prod_eq_bot {R : Type*} [CommRing R] [IsDomain R] {s : Multiset (Ideal R)} :
    s.prod = ⊥ ↔ ∃ I ∈ s, I = ⊥ := by
  rw [bot_eq_zero, prod_zero_iff_exists_zero]
  

Proof state:
R✝ : Type u
ι : Type u_1
inst✝² : CommSemiring R✝
I J K L : Ideal R✝
R : Type u_2
inst✝¹ : CommRing R
inst✝ : IsDomain R
s : Multiset (Ideal R)
⊢ (∃ r, ∃ (_ : r ∈ s), r = 0) ↔ ∃ I ∈ s, I = 0

Next tactic:
simp
theorem span_pair_mul_span_pair (w x y z : R) :
    (span {w, x} : Ideal R) * span {y, z} = span {w * y, w * z, x * y, x * z} := by
  

Proof state:
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
w x y z : R
⊢ span {w, x} * span {y, z} = span {w * y, w * z, x * y, x * z}

Next tactic:
simp_rw [span_insert, sup_mul, mul_sup, span_singleton_mul_span_singleton, sup_assoc]
theorem isCoprime_iff_codisjoint : IsCoprime I J ↔ Codisjoint I J := by
  

Proof state:
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
⊢ IsCoprime I J ↔ Codisjoint I J

Next tactic:
rw [IsCoprime, codisjoint_iff]
theorem isCoprime_iff_codisjoint : IsCoprime I J ↔ Codisjoint I J := by
  rw [IsCoprime, codisjoint_iff]
  

Proof state:
R : Type u
ι : Type u_1
inst✝ : CommSemiring R
I J K L : Ideal R
⊢ (∃ a b, a * I + b * J = 1) ↔ I ⊔ J = ⊤

Next tactic:
constructor