l3lab/ntp-mathlib huggingface dataset:
set_option maxHeartbeats 500000 in
theorem comp_assoc (r : FormalMultilinearSeries 𝕜 G H) (q : FormalMultilinearSeries 𝕜 F G)
    (p : FormalMultilinearSeries 𝕜 E F) : (r.comp q).comp p = r.comp (q.comp p) := by
  ext n v
  /- First, rewrite the two compositions appearing in the theorem as two sums over complicated
    sigma types, as in the description of the proof above. -/
  let f : (Σ a : Composition n, Composition a.length) → H := fun c =>
    r c.2.length (applyComposition q c.2 (applyComposition p c.1 v))
  let g : (Σ c : Composition n, ∀ i : Fin c.length, Composition (c.blocksFun i)) → H := fun c =>
    r c.1.length fun i : Fin c.1.length =>
      q (c.2 i).length (applyComposition p (c.2 i) (v ∘ c.1.embedding i))
  suffices ∑ c, f c = ∑ c, g c by
    simpa (config := { unfoldPartialApp := true }) only [FormalMultilinearSeries.comp,
      ContinuousMultilinearMap.sum_apply, compAlongComposition_apply, Finset.sum_sigma',
      applyComposition, ContinuousMultilinearMap.map_sum]
  /- Now, we use `Composition.sigmaEquivSigmaPi n` to change
    variables in the second sum, and check that we get exactly the same sums. -/
  rw [← (sigmaEquivSigmaPi n).sum_comp]
  /- To check that we have the same terms, we should check that we apply the same component of
    `r`, and the same component of `q`, and the same component of `p`, to the same coordinate of
    `v`. This is true by definition, but at each step one needs to convince Lean that the types
    one considers are the same, using a suitable congruence lemma to avoid dependent type issues.
    This dance has to be done three times, one for `r`, one for `q` and one for `p`.-/
  apply Finset.sum_congr rfl
  rintro ⟨a, b⟩ _
  dsimp [sigmaEquivSigmaPi]
  -- check that the `r` components are the same. Based on `Composition.length_gather`
  

Proof state:
case h.H.mk
𝕜 : Type u_1
E : Type u_2
F : Type u_3
G : Type u_4
H : Type u_5
inst✝⁸ : NontriviallyNormedField 𝕜
inst✝⁷ : NormedAddCommGroup E
inst✝⁶ : NormedSpace 𝕜 E
inst✝⁵ : NormedAddCommGroup F
inst✝⁴ : NormedSpace 𝕜 F
inst✝³ : NormedAddCommGroup G
inst✝² : NormedSpace 𝕜 G
inst✝¹ : NormedAddCommGroup H
inst✝ : NormedSpace 𝕜 H
r : FormalMultilinearSeries 𝕜 G H
q : FormalMultilinearSeries 𝕜 F G
p : FormalMultilinearSeries 𝕜 E F
n : ℕ
v : Fin n → E
f : (a : Composition n) × Composition (Composition.length a) → H :=
  fun c => (r (Composition.length c.snd)) (applyComposition q c.snd (applyComposition p c.fst v))
g : (c : Composition n) × ((i : Fin (Composition.length c)) → Composition (blocksFun c i)) → H :=
  fun c =>
    (r (Composition.length c.fst)) fun i =>
      (q (Composition.length (Sigma.snd c i))) (applyComposition p (Sigma.snd c i) (v ∘ ⇑(embedding c.fst i)))
a : Composition n
b : Composition (Composition.length a)
a✝ : { fst := a, snd := b } ∈ Finset.univ
⊢ (r (Composition.length b)) (applyComposition q b (applyComposition p a v)) =
    (r (Composition.length (gather a b))) fun i =>
      (q (Composition.length (sigmaCompositionAux a b i)))
        (applyComposition p (sigmaCompositionAux a b i) (v ∘ ⇑(embedding (gather a b) i)))

Next tactic:
apply r.congr (Composition.length_gather a b).symm
@[aesop safe apply (rule_sets [SetLike])]
theorem natCast_mem [AddSubmonoidWithOneClass S R] (n : ℕ) : (n : R) ∈ s := by
  

Proof state:
S : Type u_1
R : Type u_2
inst✝² : AddMonoidWithOne R
inst✝¹ : SetLike S R
s : S
inst✝ : AddSubmonoidWithOneClass S R
n : ℕ
⊢ ↑n ∈ s

Next tactic:
induction n
@[aesop safe apply (rule_sets [SetLike])]
theorem natCast_mem [AddSubmonoidWithOneClass S R] (n : ℕ) : (n : R) ∈ s := by
  induction n <;> 

Proof state:
case zero
S : Type u_1
R : Type u_2
inst✝² : AddMonoidWithOne R
inst✝¹ : SetLike S R
s : S
inst✝ : AddSubmonoidWithOneClass S R
⊢ ↑Nat.zero ∈ s

Next tactic:
simp [zero_mem, add_mem, one_mem, *]
@[aesop safe apply (rule_sets [SetLike])]
theorem natCast_mem [AddSubmonoidWithOneClass S R] (n : ℕ) : (n : R) ∈ s := by
  induction n <;> 

Proof state:
case succ
S : Type u_1
R : Type u_2
inst✝² : AddMonoidWithOne R
inst✝¹ : SetLike S R
s : S
inst✝ : AddSubmonoidWithOneClass S R
n✝ : ℕ
n_ih✝ : ↑n✝ ∈ s
⊢ ↑(Nat.succ n✝) ∈ s

Next tactic:
simp [zero_mem, add_mem, one_mem, *]
@[aesop safe apply (rule_sets [SetLike])]
lemma ofNat_mem [AddSubmonoidWithOneClass S R] (s : S) (n : ℕ) [n.AtLeastTwo] :
    no_index (OfNat.ofNat n) ∈ s := by
  

Proof state:
S : Type u_1
R : Type u_2
inst✝³ : AddMonoidWithOne R
inst✝² : SetLike S R
s✝ : S
inst✝¹ : AddSubmonoidWithOneClass S R
s : S
n : ℕ
inst✝ : Nat.AtLeastTwo n
⊢ OfNat.ofNat n ∈ s

Next tactic:
rw [← Nat.cast_eq_ofNat]
@[aesop safe apply (rule_sets [SetLike])]
lemma ofNat_mem [AddSubmonoidWithOneClass S R] (s : S) (n : ℕ) [n.AtLeastTwo] :
    no_index (OfNat.ofNat n) ∈ s := by
  rw [← Nat.cast_eq_ofNat]; 

Proof state:
S : Type u_1
R : Type u_2
inst✝³ : AddMonoidWithOne R
inst✝² : SetLike S R
s✝ : S
inst✝¹ : AddSubmonoidWithOneClass S R
s : S
n : ℕ
inst✝ : Nat.AtLeastTwo n
⊢ ↑n ∈ s

Next tactic:
exact natCast_mem s n
theorem coe_nat_mem (n : ℕ) : (n : R) ∈ s := by
  

Proof state:
R : Type u
S : Type v
T : Type w
inst✝¹ : NonAssocSemiring R
M : Submonoid R
inst✝ : SetLike S R
hSR : SubsemiringClass S R
s : S
n : ℕ
⊢ ↑n ∈ s

Next tactic:
rw [← nsmul_one]
theorem coe_nat_mem (n : ℕ) : (n : R) ∈ s := by
  rw [← nsmul_one]
  

Proof state:
R : Type u
S : Type v
T : Type w
inst✝¹ : NonAssocSemiring R
M : Submonoid R
inst✝ : SetLike S R
hSR : SubsemiringClass S R
s : S
n : ℕ
⊢ n • 1 ∈ s

Next tactic:
exact nsmul_mem (one_mem _) _
@[simp, norm_cast]
theorem coe_pow {R} [Semiring R] [SetLike S R] [SubsemiringClass S R] (x : s) (n : ℕ) :
    ((x ^ n : s) : R) = (x : R) ^ n := by
  

Proof state:
R✝ : Type u
S : Type v
T : Type w
inst✝⁴ : NonAssocSemiring R✝
M : Submonoid R✝
inst✝³ : SetLike S R✝
hSR : SubsemiringClass S R✝
s : S
R : Type u_1
inst✝² : Semiring R
inst✝¹ : SetLike S R
inst✝ : SubsemiringClass S R
x : ↥s
n : ℕ
⊢ ↑(x ^ n) = ↑x ^ n

Next tactic:
induction' n with n ih
@[simp, norm_cast]
theorem coe_pow {R} [Semiring R] [SetLike S R] [SubsemiringClass S R] (x : s) (n : ℕ) :
    ((x ^ n : s) : R) = (x : R) ^ n := by
  induction' n with n ih
  · 

Proof state:
case zero
R✝ : Type u
S : Type v
T : Type w
inst✝⁴ : NonAssocSemiring R✝
M : Submonoid R✝
inst✝³ : SetLike S R✝
hSR : SubsemiringClass S R✝
s : S
R : Type u_1
inst✝² : Semiring R
inst✝¹ : SetLike S R
inst✝ : SubsemiringClass S R
x : ↥s
⊢ ↑(x ^ Nat.zero) = ↑x ^ Nat.zero

Next tactic:
simp
@[simp, norm_cast]
theorem coe_pow {R} [Semiring R] [SetLike S R] [SubsemiringClass S R] (x : s) (n : ℕ) :
    ((x ^ n : s) : R) = (x : R) ^ n := by
  induction' n with n ih
  · simp
  · 

Proof state:
case succ
R✝ : Type u
S : Type v
T : Type w
inst✝⁴ : NonAssocSemiring R✝
M : Submonoid R✝
inst✝³ : SetLike S R✝
hSR : SubsemiringClass S R✝
s : S
R : Type u_1
inst✝² : Semiring R
inst✝¹ : SetLike S R
inst✝ : SubsemiringClass S R
x : ↥s
n : ℕ
ih : ↑(x ^ n) = ↑x ^ n
⊢ ↑(x ^ Nat.succ n) = ↑x ^ Nat.succ n

Next tactic:
simp [pow_succ, ih]
instance : SetLike (Subsemiring R) R
    where
  coe s := s.carrier
  coe_injective' p q h := by 

Proof state:
R : Type u
S : Type v
T : Type w
inst✝² : NonAssocSemiring R
M : Submonoid R
inst✝¹ : NonAssocSemiring S
inst✝ : NonAssocSemiring T
p q : Subsemiring R
h : (fun s => s.carrier) p = (fun s => s.carrier) q
⊢ p = q

Next tactic:
cases p
instance : SetLike (Subsemiring R) R
    where
  coe s := s.carrier
  coe_injective' p q h := by cases p; 

Proof state:
case mk
R : Type u
S : Type v
T : Type w
inst✝² : NonAssocSemiring R
M : Submonoid R
inst✝¹ : NonAssocSemiring S
inst✝ : NonAssocSemiring T
q : Subsemiring R
toSubmonoid✝ : Submonoid R
add_mem'✝ : ∀ {a b : R}, a ∈ toSubmonoid✝.carrier → b ∈ toSubmonoid✝.carrier → a + b ∈ toSubmonoid✝.carrier
zero_mem'✝ : 0 ∈ toSubmonoid✝.carrier
h :
  (fun s => s.carrier) { toSubmonoid := toSubmonoid✝, add_mem' := add_mem'✝, zero_mem' := zero_mem'✝ } =
    (fun s => s.carrier) q
⊢ { toSubmonoid := toSubmonoid✝, add_mem' := add_mem'✝, zero_mem' := zero_mem'✝ } = q

Next tactic:
cases q
instance : SetLike (Subsemiring R) R
    where
  coe s := s.carrier
  coe_injective' p q h := by cases p; cases q; 

Proof state:
case mk.mk
R : Type u
S : Type v
T : Type w
inst✝² : NonAssocSemiring R
M : Submonoid R
inst✝¹ : NonAssocSemiring S
inst✝ : NonAssocSemiring T
toSubmonoid✝¹ : Submonoid R
add_mem'✝¹ : ∀ {a b : R}, a ∈ toSubmonoid✝¹.carrier → b ∈ toSubmonoid✝¹.carrier → a + b ∈ toSubmonoid✝¹.carrier
zero_mem'✝¹ : 0 ∈ toSubmonoid✝¹.carrier
toSubmonoid✝ : Submonoid R
add_mem'✝ : ∀ {a b : R}, a ∈ toSubmonoid✝.carrier → b ∈ toSubmonoid✝.carrier → a + b ∈ toSubmonoid✝.carrier
zero_mem'✝ : 0 ∈ toSubmonoid✝.carrier
h :
  (fun s => s.carrier) { toSubmonoid := toSubmonoid✝¹, add_mem' := add_mem'✝¹, zero_mem' := zero_mem'✝¹ } =
    (fun s => s.carrier) { toSubmonoid := toSubmonoid✝, add_mem' := add_mem'✝, zero_mem' := zero_mem'✝ }
⊢ { toSubmonoid := toSubmonoid✝¹, add_mem' := add_mem'✝¹, zero_mem' := zero_mem'✝¹ } =
    { toSubmonoid := toSubmonoid✝, add_mem' := add_mem'✝, zero_mem' := zero_mem'✝ }

Next tactic:
congr
instance : SetLike (Subsemiring R) R
    where
  coe s := s.carrier
  coe_injective' p q h := by cases p; cases q; congr; 

Proof state:
case mk.mk.e_toSubmonoid
R : Type u
S : Type v
T : Type w
inst✝² : NonAssocSemiring R
M : Submonoid R
inst✝¹ : NonAssocSemiring S
inst✝ : NonAssocSemiring T
toSubmonoid✝¹ : Submonoid R
add_mem'✝¹ : ∀ {a b : R}, a ∈ toSubmonoid✝¹.carrier → b ∈ toSubmonoid✝¹.carrier → a + b ∈ toSubmonoid✝¹.carrier
zero_mem'✝¹ : 0 ∈ toSubmonoid✝¹.carrier
toSubmonoid✝ : Submonoid R
add_mem'✝ : ∀ {a b : R}, a ∈ toSubmonoid✝.carrier → b ∈ toSubmonoid✝.carrier → a + b ∈ toSubmonoid✝.carrier
zero_mem'✝ : 0 ∈ toSubmonoid✝.carrier
h :
  (fun s => s.carrier) { toSubmonoid := toSubmonoid✝¹, add_mem' := add_mem'✝¹, zero_mem' := zero_mem'✝¹ } =
    (fun s => s.carrier) { toSubmonoid := toSubmonoid✝, add_mem' := add_mem'✝, zero_mem' := zero_mem'✝ }
⊢ toSubmonoid✝¹ = toSubmonoid✝

Next tactic:
exact SetLike.coe_injective' h
/-- Construct a `Subsemiring R` from a set `s`, a submonoid `sm`, and an additive
submonoid `sa` such that `x ∈ s ↔ x ∈ sm ↔ x ∈ sa`. -/
protected def mk' (s : Set R) (sm : Submonoid R) (hm : ↑sm = s) (sa : AddSubmonoid R)
    (ha : ↑sa = s) : Subsemiring R where
  carrier := s
  zero_mem' := by exact ha ▸ sa.zero_mem
  one_mem' := by exact hm ▸ sm.one_mem
  add_mem' {x y} := by simpa only [← ha] using sa.add_mem
  mul_mem' {x y} := by 

Proof state:
R : Type u
S : Type v
T : Type w
inst✝² : NonAssocSemiring R
M : Submonoid R
inst✝¹ : NonAssocSemiring S
inst✝ : NonAssocSemiring T
s : Set R
sm : Submonoid R
hm : ↑sm = s
sa : AddSubmonoid R
ha : ↑sa = s
x y : R
⊢ x ∈ s → y ∈ s → x * y ∈ s

Next tactic:
simpa only [← hm] using sm.mul_mem
/-- Construct a `Subsemiring R` from a set `s`, a submonoid `sm`, and an additive
submonoid `sa` such that `x ∈ s ↔ x ∈ sm ↔ x ∈ sa`. -/
protected def mk' (s : Set R) (sm : Submonoid R) (hm : ↑sm = s) (sa : AddSubmonoid R)
    (ha : ↑sa = s) : Subsemiring R where
  carrier := s
  zero_mem' := by exact ha ▸ sa.zero_mem
  one_mem' := by 

Proof state:
R : Type u
S : Type v
T : Type w
inst✝² : NonAssocSemiring R
M : Submonoid R
inst✝¹ : NonAssocSemiring S
inst✝ : NonAssocSemiring T
s : Set R
sm : Submonoid R
hm : ↑sm = s
sa : AddSubmonoid R
ha : ↑sa = s
⊢ 1 ∈ { carrier := s, mul_mem' := (_ : ∀ {x y : R}, x ∈ s → y ∈ s → x * y ∈ s) }.carrier

Next tactic:
exact hm ▸ sm.one_mem
/-- Construct a `Subsemiring R` from a set `s`, a submonoid `sm`, and an additive
submonoid `sa` such that `x ∈ s ↔ x ∈ sm ↔ x ∈ sa`. -/
protected def mk' (s : Set R) (sm : Submonoid R) (hm : ↑sm = s) (sa : AddSubmonoid R)
    (ha : ↑sa = s) : Subsemiring R where
  carrier := s
  zero_mem' := by exact ha ▸ sa.zero_mem
  one_mem' := by exact hm ▸ sm.one_mem
  add_mem' {x y} := by 

Proof state:
R : Type u
S : Type v
T : Type w
inst✝² : NonAssocSemiring R
M : Submonoid R
inst✝¹ : NonAssocSemiring S
inst✝ : NonAssocSemiring T
s : Set R
sm : Submonoid R
hm : ↑sm = s
sa : AddSubmonoid R
ha : ↑sa = s
x y : R
⊢ x ∈
      { toSubsemigroup := { carrier := s, mul_mem' := (_ : ∀ {x y : R}, x ∈ s → y ∈ s → x * y ∈ s) },
            one_mem' :=
              (_ :
                1 ∈
                  { carrier := s,
                      mul_mem' := (_ : ∀ {x y : R}, x ∈ s → y ∈ s → x * y ∈ s) }.carrier) }.toSubsemigroup.carrier →
    y ∈
        { toSubsemigroup := { carrier := s, mul_mem' := (_ : ∀ {x y : R}, x ∈ s → y ∈ s → x * y ∈ s) },
              one_mem' :=
                (_ :
                  1 ∈
                    { carrier := s,
                        mul_mem' := (_ : ∀ {x y : R}, x ∈ s → y ∈ s → x * y ∈ s) }.carrier) }.toSubsemigroup.carrier →
      x + y ∈
        { toSubsemigroup := { carrier := s, mul_mem' := (_ : ∀ {x y : R}, x ∈ s → y ∈ s → x * y ∈ s) },
              one_mem' :=
                (_ :
                  1 ∈
                    { carrier := s,
                        mul_mem' := (_ : ∀ {x y : R}, x ∈ s → y ∈ s → x * y ∈ s) }.carrier) }.toSubsemigroup.carrier

Next tactic:
simpa only [← ha] using sa.add_mem
/-- Construct a `Subsemiring R` from a set `s`, a submonoid `sm`, and an additive
submonoid `sa` such that `x ∈ s ↔ x ∈ sm ↔ x ∈ sa`. -/
protected def mk' (s : Set R) (sm : Submonoid R) (hm : ↑sm = s) (sa : AddSubmonoid R)
    (ha : ↑sa = s) : Subsemiring R where
  carrier := s
  zero_mem' := by 

Proof state:
R : Type u
S : Type v
T : Type w
inst✝² : NonAssocSemiring R
M : Submonoid R
inst✝¹ : NonAssocSemiring S
inst✝ : NonAssocSemiring T
s : Set R
sm : Submonoid R
hm : ↑sm = s
sa : AddSubmonoid R
ha : ↑sa = s
⊢ 0 ∈
    { toSubsemigroup := { carrier := s, mul_mem' := (_ : ∀ {x y : R}, x ∈ s → y ∈ s → x * y ∈ s) },
          one_mem' :=
            (_ :
              1 ∈
                { carrier := s,
                    mul_mem' := (_ : ∀ {x y : R}, x ∈ s → y ∈ s → x * y ∈ s) }.carrier) }.toSubsemigroup.carrier

Next tactic:
exact ha ▸ sa.zero_mem
@[simp, norm_cast]
theorem coe_pow {R} [Semiring R] (s : Subsemiring R) (x : s) (n : ℕ) :
    ((x ^ n : s) : R) = (x : R) ^ n := by
  

Proof state:
R✝ : Type u
S : Type v
T : Type w
inst✝³ : NonAssocSemiring R✝
M : Submonoid R✝
inst✝² : NonAssocSemiring S
inst✝¹ : NonAssocSemiring T
s✝ : Subsemiring R✝
R : Type u_1
inst✝ : Semiring R
s : Subsemiring R
x : ↥s
n : ℕ
⊢ ↑(x ^ n) = ↑x ^ n

Next tactic:
induction' n with n ih
@[simp, norm_cast]
theorem coe_pow {R} [Semiring R] (s : Subsemiring R) (x : s) (n : ℕ) :
    ((x ^ n : s) : R) = (x : R) ^ n := by
  induction' n with n ih
  · 

Proof state:
case zero
R✝ : Type u
S : Type v
T : Type w
inst✝³ : NonAssocSemiring R✝
M : Submonoid R✝
inst✝² : NonAssocSemiring S
inst✝¹ : NonAssocSemiring T
s✝ : Subsemiring R✝
R : Type u_1
inst✝ : Semiring R
s : Subsemiring R
x : ↥s
⊢ ↑(x ^ Nat.zero) = ↑x ^ Nat.zero

Next tactic:
simp
@[simp, norm_cast]
theorem coe_pow {R} [Semiring R] (s : Subsemiring R) (x : s) (n : ℕ) :
    ((x ^ n : s) : R) = (x : R) ^ n := by
  induction' n with n ih
  · simp
  · 

Proof state:
case succ
R✝ : Type u
S : Type v
T : Type w
inst✝³ : NonAssocSemiring R✝
M : Submonoid R✝
inst✝² : NonAssocSemiring S
inst✝¹ : NonAssocSemiring T
s✝ : Subsemiring R✝
R : Type u_1
inst✝ : Semiring R
s : Subsemiring R
x : ↥s
n : ℕ
ih : ↑(x ^ n) = ↑x ^ n
⊢ ↑(x ^ Nat.succ n) = ↑x ^ Nat.succ n

Next tactic:
simp [pow_succ, ih]
@[simp]
theorem mem_map {f : R →+* S} {s : Subsemiring R} {y : S} : y ∈ s.map f ↔ ∃ x ∈ s, f x = y := by
  -- Porting note: was `exact Set.mem_image_iff_bex`
  

Proof state:
R : Type u
S : Type v
T : Type w
inst✝² : NonAssocSemiring R
M : Submonoid R
inst✝¹ : NonAssocSemiring S
inst✝ : NonAssocSemiring T
s✝ : Subsemiring R
f : R →+* S
s : Subsemiring R
y : S
⊢ y ∈ map f s ↔ ∃ x ∈ s, f x = y

Next tactic:
convert Set.mem_image_iff_bex (f := f) (s := s.carrier) (y := y) using 1
@[simp]
theorem mem_map {f : R →+* S} {s : Subsemiring R} {y : S} : y ∈ s.map f ↔ ∃ x ∈ s, f x = y := by
  -- Porting note: was `exact Set.mem_image_iff_bex`
  convert Set.mem_image_iff_bex (f := f) (s := s.carrier) (y := y) using 1
  

Proof state:
case h.e'_2.a
R : Type u
S : Type v
T : Type w
inst✝² : NonAssocSemiring R
M : Submonoid R
inst✝¹ : NonAssocSemiring S
inst✝ : NonAssocSemiring T
s✝ : Subsemiring R
f : R →+* S
s : Subsemiring R
y : S
⊢ (∃ x ∈ s, f x = y) ↔ ∃ x, ∃ (_ : x ∈ s.carrier), f x = y

Next tactic:
simp
theorem rangeS_eq_map (f : R →+* S) : f.rangeS = (⊤ : Subsemiring R).map f := by
  

Proof state:
R : Type u
S : Type v
T : Type w
inst✝² : NonAssocSemiring R
M : Submonoid R
inst✝¹ : NonAssocSemiring S
inst✝ : NonAssocSemiring T
g : S →+* T
f✝ f : R →+* S
⊢ rangeS f = Subsemiring.map f ⊤

Next tactic:
ext
theorem rangeS_eq_map (f : R →+* S) : f.rangeS = (⊤ : Subsemiring R).map f := by
  ext
  

Proof state:
case h
R : Type u
S : Type v
T : Type w
inst✝² : NonAssocSemiring R
M : Submonoid R
inst✝¹ : NonAssocSemiring S
inst✝ : NonAssocSemiring T
g : S →+* T
f✝ f : R →+* S
x✝ : S
⊢ x✝ ∈ rangeS f ↔ x✝ ∈ Subsemiring.map f ⊤

Next tactic:
simp
theorem map_rangeS : f.rangeS.map g = (g.comp f).rangeS := by
  

Proof state:
R : Type u
S : Type v
T : Type w
inst✝² : NonAssocSemiring R
M : Submonoid R
inst✝¹ : NonAssocSemiring S
inst✝ : NonAssocSemiring T
g : S →+* T
f : R →+* S
⊢ Subsemiring.map g (rangeS f) = rangeS (comp g f)

Next tactic:
simpa only [rangeS_eq_map] using (⊤ : Subsemiring R).map_map g f
instance : InfSet (Subsemiring R) :=
  ⟨fun s =>
    Subsemiring.mk' (⋂ t ∈ s, ↑t) (⨅ t ∈ s, Subsemiring.toSubmonoid t) (by 

Proof state:
R : Type u
S : Type v
T : Type w
inst✝² : NonAssocSemiring R
M : Submonoid R
inst✝¹ : NonAssocSemiring S
inst✝ : NonAssocSemiring T
s : Set (Subsemiring R)
⊢ ↑(⨅ t ∈ s, t.toSubmonoid) = ⋂ t ∈ s, ↑t

Next tactic:
simp
instance : InfSet (Subsemiring R) :=
  ⟨fun s =>
    Subsemiring.mk' (⋂ t ∈ s, ↑t) (⨅ t ∈ s, Subsemiring.toSubmonoid t) (by simp)
      (⨅ t ∈ s, Subsemiring.toAddSubmonoid t)
      (by 

Proof state:
R : Type u
S : Type v
T : Type w
inst✝² : NonAssocSemiring R
M : Submonoid R
inst✝¹ : NonAssocSemiring S
inst✝ : NonAssocSemiring T
s : Set (Subsemiring R)
⊢ ↑(⨅ t ∈ s, toAddSubmonoid t) = ⋂ t ∈ s, ↑t

Next tactic:
simp
theorem mem_map_equiv {f : R ≃+* S} {K : Subsemiring R} {x : S} :
    x ∈ K.map (f : R →+* S) ↔ f.symm x ∈ K := by
  

Proof state:
R : Type u
S : Type v
T : Type w
inst✝² : NonAssocSemiring R
M : Submonoid R
inst✝¹ : NonAssocSemiring S
inst✝ : NonAssocSemiring T
f : R ≃+* S
K : Subsemiring R
x : S
⊢ x ∈ map (↑f) K ↔ (RingEquiv.symm f) x ∈ K

Next tactic:
convert @Set.mem_image_equiv _ _ (↑K) f.toEquiv x using 1
/-- The `Subsemiring` generated by a multiplicative submonoid coincides with the
`Subsemiring.closure` of the submonoid itself . -/
theorem subsemiringClosure_eq_closure : M.subsemiringClosure = Subsemiring.closure (M : Set R) := by
  

Proof state:
R : Type u
S : Type v
T : Type w
inst✝² : NonAssocSemiring R
M : Submonoid R
inst✝¹ : NonAssocSemiring S
inst✝ : NonAssocSemiring T
⊢ subsemiringClosure M = Subsemiring.closure ↑M

Next tactic:
ext
/-- The `Subsemiring` generated by a multiplicative submonoid coincides with the
`Subsemiring.closure` of the submonoid itself . -/
theorem subsemiringClosure_eq_closure : M.subsemiringClosure = Subsemiring.closure (M : Set R) := by
  ext
  

Proof state:
case h
R : Type u
S : Type v
T : Type w
inst✝² : NonAssocSemiring R
M : Submonoid R
inst✝¹ : NonAssocSemiring S
inst✝ : NonAssocSemiring T
x✝ : R
⊢ x✝ ∈ subsemiringClosure M ↔ x✝ ∈ Subsemiring.closure ↑M

Next tactic:
refine'
    ⟨fun hx => _, fun hx =>
      (Subsemiring.mem_closure.mp hx) M.subsemiringClosure fun s sM => _⟩
/-- The `Subsemiring` generated by a multiplicative submonoid coincides with the
`Subsemiring.closure` of the submonoid itself . -/
theorem subsemiringClosure_eq_closure : M.subsemiringClosure = Subsemiring.closure (M : Set R) := by
  ext
  refine'
    ⟨fun hx => _, fun hx =>
      (Subsemiring.mem_closure.mp hx) M.subsemiringClosure fun s sM => _⟩
  <;> 

Proof state:
case h.refine'_1
R : Type u
S : Type v
T : Type w
inst✝² : NonAssocSemiring R
M : Submonoid R
inst✝¹ : NonAssocSemiring S
inst✝ : NonAssocSemiring T
x✝ : R
hx : x✝ ∈ subsemiringClosure M
⊢ x✝ ∈ Subsemiring.closure ↑M

Next tactic:
rintro - ⟨H1, rfl⟩
/-- The `Subsemiring` generated by a multiplicative submonoid coincides with the
`Subsemiring.closure` of the submonoid itself . -/
theorem subsemiringClosure_eq_closure : M.subsemiringClosure = Subsemiring.closure (M : Set R) := by
  ext
  refine'
    ⟨fun hx => _, fun hx =>
      (Subsemiring.mem_closure.mp hx) M.subsemiringClosure fun s sM => _⟩
  <;> 

Proof state:
case h.refine'_2
R : Type u
S : Type v
T : Type w
inst✝² : NonAssocSemiring R
M : Submonoid R
inst✝¹ : NonAssocSemiring S
inst✝ : NonAssocSemiring T
x✝ : R
hx : x✝ ∈ Subsemiring.closure ↑M
s : R
sM : s ∈ ↑M
⊢ s ∈ ↑(subsemiringClosure M)

Next tactic:
rintro - ⟨H1, rfl⟩
/-- The `Subsemiring` generated by a multiplicative submonoid coincides with the
`Subsemiring.closure` of the submonoid itself . -/
theorem subsemiringClosure_eq_closure : M.subsemiringClosure = Subsemiring.closure (M : Set R) := by
  ext
  refine'
    ⟨fun hx => _, fun hx =>
      (Subsemiring.mem_closure.mp hx) M.subsemiringClosure fun s sM => _⟩
  <;> rintro - ⟨H1, rfl⟩
  <;> 

Proof state:
case h.refine'_1.intro
R : Type u
S : Type v
T : Type w
inst✝² : NonAssocSemiring R
M : Submonoid R
inst✝¹ : NonAssocSemiring S
inst✝ : NonAssocSemiring T
x✝ : R
hx : x✝ ∈ subsemiringClosure M
H1 : Subsemiring R
⊢ x✝ ∈ (fun t => ⋂ (_ : t ∈ {S | ↑M ⊆ ↑S}), ↑t) H1

Next tactic:
rintro - ⟨H2, rfl⟩
/-- The `Subsemiring` generated by a multiplicative submonoid coincides with the
`Subsemiring.closure` of the submonoid itself . -/
theorem subsemiringClosure_eq_closure : M.subsemiringClosure = Subsemiring.closure (M : Set R) := by
  ext
  refine'
    ⟨fun hx => _, fun hx =>
      (Subsemiring.mem_closure.mp hx) M.subsemiringClosure fun s sM => _⟩
  <;> rintro - ⟨H1, rfl⟩
  <;> 

Proof state:
case h.refine'_2.intro
R : Type u
S : Type v
T : Type w
inst✝² : NonAssocSemiring R
M : Submonoid R
inst✝¹ : NonAssocSemiring S
inst✝ : NonAssocSemiring T
x✝ : R
hx : x✝ ∈ Subsemiring.closure ↑M
s : R
sM : s ∈ ↑M
H1 : AddSubmonoid R
⊢ s ∈ (fun t => ⋂ (_ : t ∈ {S | ↑M ⊆ ↑S}), ↑t) H1

Next tactic:
rintro - ⟨H2, rfl⟩
/-- The `Subsemiring` generated by a multiplicative submonoid coincides with the
`Subsemiring.closure` of the submonoid itself . -/
theorem subsemiringClosure_eq_closure : M.subsemiringClosure = Subsemiring.closure (M : Set R) := by
  ext
  refine'
    ⟨fun hx => _, fun hx =>
      (Subsemiring.mem_closure.mp hx) M.subsemiringClosure fun s sM => _⟩
  <;> rintro - ⟨H1, rfl⟩
  <;> rintro - ⟨H2, rfl⟩
  · 

Proof state:
case h.refine'_1.intro.intro
R : Type u
S : Type v
T : Type w
inst✝² : NonAssocSemiring R
M : Submonoid R
inst✝¹ : NonAssocSemiring S
inst✝ : NonAssocSemiring T
x✝ : R
hx : x✝ ∈ subsemiringClosure M
H1 : Subsemiring R
H2 : H1 ∈ {S | ↑M ⊆ ↑S}
⊢ x✝ ∈ (fun h => ↑H1) H2

Next tactic:
exact AddSubmonoid.mem_closure.mp hx H1.toAddSubmonoid H2
/-- The `Subsemiring` generated by a multiplicative submonoid coincides with the
`Subsemiring.closure` of the submonoid itself . -/
theorem subsemiringClosure_eq_closure : M.subsemiringClosure = Subsemiring.closure (M : Set R) := by
  ext
  refine'
    ⟨fun hx => _, fun hx =>
      (Subsemiring.mem_closure.mp hx) M.subsemiringClosure fun s sM => _⟩
  <;> rintro - ⟨H1, rfl⟩
  <;> rintro - ⟨H2, rfl⟩
  · exact AddSubmonoid.mem_closure.mp hx H1.toAddSubmonoid H2
  · 

Proof state:
case h.refine'_2.intro.intro
R : Type u
S : Type v
T : Type w
inst✝² : NonAssocSemiring R
M : Submonoid R
inst✝¹ : NonAssocSemiring S
inst✝ : NonAssocSemiring T
x✝ : R
hx : x✝ ∈ Subsemiring.closure ↑M
s : R
sM : s ∈ ↑M
H1 : AddSubmonoid R
H2 : H1 ∈ {S | ↑M ⊆ ↑S}
⊢ s ∈ (fun h => ↑H1) H2

Next tactic:
exact H2 sM
/-- The elements of the subsemiring closure of `M` are exactly the elements of the additive closure
of a multiplicative submonoid `M`. -/
theorem coe_closure_eq (s : Set R) :
    (closure s : Set R) = AddSubmonoid.closure (Submonoid.closure s : Set R) := by
  

Proof state:
R : Type u
S : Type v
T : Type w
inst✝² : NonAssocSemiring R
M : Submonoid R
inst✝¹ : NonAssocSemiring S
inst✝ : NonAssocSemiring T
s : Set R
⊢ ↑(closure s) = ↑(AddSubmonoid.closure ↑(Submonoid.closure s))

Next tactic:
simp [← Submonoid.subsemiringClosure_toAddSubmonoid, Submonoid.subsemiringClosure_eq_closure]