l3lab/ntp-mathlib huggingface dataset:
protected theorem map_mul {A'} [Semiring A'] [Algebra R A'] (f : A →ₐ[R] A') :
    map f.toLinearMap (M * N) = map f.toLinearMap M * map f.toLinearMap N :=
  calc
    map f.toLinearMap (M * N) = ⨆ i : M, (N.map (LinearMap.mul R A i)).map f.toLinearMap :=
      map_iSup _ _
    _ = map f.toLinearMap M * map f.toLinearMap N := by
      apply congr_arg sSup
      ext S
      constructor <;> rintro ⟨y, hy⟩
      · use ⟨f y, mem_map.mpr ⟨y.1, y.2, rfl⟩⟩  -- porting note: added `⟨⟩`
        refine' Eq.trans _ hy
        ext
        simp
      · obtain ⟨y', hy', fy_eq⟩ := mem_map.mp y.2
        use ⟨y', hy'⟩  -- porting note: added `⟨⟩`
        

Proof state:
case h
ι : Sort uι
R : Type u
inst✝⁴ : CommSemiring R
A : Type v
inst✝³ : Semiring A
inst✝² : Algebra R A
S✝ T : Set A
M N P Q : Submodule R A
m n : A
A' : Type u_1
inst✝¹ : Semiring A'
inst✝ : Algebra R A'
f : A →ₐ[R] A'
S : Submodule R A'
y : ↥(map (AlgHom.toLinearMap f) M)
hy : (fun s => map ((LinearMap.mul R A') ↑s) (map (AlgHom.toLinearMap f) N)) y = S
y' : A
hy' : y' ∈ M
fy_eq : (AlgHom.toLinearMap f) y' = ↑y
⊢ (fun i => map (AlgHom.toLinearMap f) (map ((LinearMap.mul R A) ↑i) N)) { val := y', property := hy' } = S

Next tactic:
refine' Eq.trans _ hy
protected theorem map_mul {A'} [Semiring A'] [Algebra R A'] (f : A →ₐ[R] A') :
    map f.toLinearMap (M * N) = map f.toLinearMap M * map f.toLinearMap N :=
  calc
    map f.toLinearMap (M * N) = ⨆ i : M, (N.map (LinearMap.mul R A i)).map f.toLinearMap :=
      map_iSup _ _
    _ = map f.toLinearMap M * map f.toLinearMap N := by
      apply congr_arg sSup
      ext S
      constructor <;> rintro ⟨y, hy⟩
      · use ⟨f y, mem_map.mpr ⟨y.1, y.2, rfl⟩⟩  -- porting note: added `⟨⟩`
        refine' Eq.trans _ hy
        ext
        simp
      · obtain ⟨y', hy', fy_eq⟩ := mem_map.mp y.2
        use ⟨y', hy'⟩  -- porting note: added `⟨⟩`
        refine' Eq.trans _ hy
        

Proof state:
case h
ι : Sort uι
R : Type u
inst✝⁴ : CommSemiring R
A : Type v
inst✝³ : Semiring A
inst✝² : Algebra R A
S✝ T : Set A
M N P Q : Submodule R A
m n : A
A' : Type u_1
inst✝¹ : Semiring A'
inst✝ : Algebra R A'
f : A →ₐ[R] A'
S : Submodule R A'
y : ↥(map (AlgHom.toLinearMap f) M)
hy : (fun s => map ((LinearMap.mul R A') ↑s) (map (AlgHom.toLinearMap f) N)) y = S
y' : A
hy' : y' ∈ M
fy_eq : (AlgHom.toLinearMap f) y' = ↑y
⊢ (fun i => map (AlgHom.toLinearMap f) (map ((LinearMap.mul R A) ↑i) N)) { val := y', property := hy' } =
    (fun s => map ((LinearMap.mul R A') ↑s) (map (AlgHom.toLinearMap f) N)) y

Next tactic:
rw [f.toLinearMap_apply] at fy_eq
protected theorem map_mul {A'} [Semiring A'] [Algebra R A'] (f : A →ₐ[R] A') :
    map f.toLinearMap (M * N) = map f.toLinearMap M * map f.toLinearMap N :=
  calc
    map f.toLinearMap (M * N) = ⨆ i : M, (N.map (LinearMap.mul R A i)).map f.toLinearMap :=
      map_iSup _ _
    _ = map f.toLinearMap M * map f.toLinearMap N := by
      apply congr_arg sSup
      ext S
      constructor <;> rintro ⟨y, hy⟩
      · use ⟨f y, mem_map.mpr ⟨y.1, y.2, rfl⟩⟩  -- porting note: added `⟨⟩`
        refine' Eq.trans _ hy
        ext
        simp
      · obtain ⟨y', hy', fy_eq⟩ := mem_map.mp y.2
        use ⟨y', hy'⟩  -- porting note: added `⟨⟩`
        refine' Eq.trans _ hy
        rw [f.toLinearMap_apply] at fy_eq
        

Proof state:
case h
ι : Sort uι
R : Type u
inst✝⁴ : CommSemiring R
A : Type v
inst✝³ : Semiring A
inst✝² : Algebra R A
S✝ T : Set A
M N P Q : Submodule R A
m n : A
A' : Type u_1
inst✝¹ : Semiring A'
inst✝ : Algebra R A'
f : A →ₐ[R] A'
S : Submodule R A'
y : ↥(map (AlgHom.toLinearMap f) M)
hy : (fun s => map ((LinearMap.mul R A') ↑s) (map (AlgHom.toLinearMap f) N)) y = S
y' : A
hy' : y' ∈ M
fy_eq : f y' = ↑y
⊢ (fun i => map (AlgHom.toLinearMap f) (map ((LinearMap.mul R A) ↑i) N)) { val := y', property := hy' } =
    (fun s => map ((LinearMap.mul R A') ↑s) (map (AlgHom.toLinearMap f) N)) y

Next tactic:
ext
protected theorem map_mul {A'} [Semiring A'] [Algebra R A'] (f : A →ₐ[R] A') :
    map f.toLinearMap (M * N) = map f.toLinearMap M * map f.toLinearMap N :=
  calc
    map f.toLinearMap (M * N) = ⨆ i : M, (N.map (LinearMap.mul R A i)).map f.toLinearMap :=
      map_iSup _ _
    _ = map f.toLinearMap M * map f.toLinearMap N := by
      apply congr_arg sSup
      ext S
      constructor <;> rintro ⟨y, hy⟩
      · use ⟨f y, mem_map.mpr ⟨y.1, y.2, rfl⟩⟩  -- porting note: added `⟨⟩`
        refine' Eq.trans _ hy
        ext
        simp
      · obtain ⟨y', hy', fy_eq⟩ := mem_map.mp y.2
        use ⟨y', hy'⟩  -- porting note: added `⟨⟩`
        refine' Eq.trans _ hy
        rw [f.toLinearMap_apply] at fy_eq
        ext
        

Proof state:
case h.h
ι : Sort uι
R : Type u
inst✝⁴ : CommSemiring R
A : Type v
inst✝³ : Semiring A
inst✝² : Algebra R A
S✝ T : Set A
M N P Q : Submodule R A
m n : A
A' : Type u_1
inst✝¹ : Semiring A'
inst✝ : Algebra R A'
f : A →ₐ[R] A'
S : Submodule R A'
y : ↥(map (AlgHom.toLinearMap f) M)
hy : (fun s => map ((LinearMap.mul R A') ↑s) (map (AlgHom.toLinearMap f) N)) y = S
y' : A
hy' : y' ∈ M
fy_eq : f y' = ↑y
x✝ : A'
⊢ x✝ ∈ (fun i => map (AlgHom.toLinearMap f) (map ((LinearMap.mul R A) ↑i) N)) { val := y', property := hy' } ↔
    x✝ ∈ (fun s => map ((LinearMap.mul R A') ↑s) (map (AlgHom.toLinearMap f) N)) y

Next tactic:
simp [fy_eq]
theorem map_op_mul :
    map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) (M * N) =
      map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) N *
        map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) M := by
  

Proof state:
ι : Sort uι
R : Type u
inst✝² : CommSemiring R
A : Type v
inst✝¹ : Semiring A
inst✝ : Algebra R A
S T : Set A
M N P Q : Submodule R A
m n : A
⊢ map (↑(opLinearEquiv R)) (M * N) = map (↑(opLinearEquiv R)) N * map (↑(opLinearEquiv R)) M

Next tactic:
apply le_antisymm
theorem map_op_mul :
    map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) (M * N) =
      map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) N *
        map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) M := by
  apply le_antisymm
  · 

Proof state:
case a
ι : Sort uι
R : Type u
inst✝² : CommSemiring R
A : Type v
inst✝¹ : Semiring A
inst✝ : Algebra R A
S T : Set A
M N P Q : Submodule R A
m n : A
⊢ map (↑(opLinearEquiv R)) (M * N) ≤ map (↑(opLinearEquiv R)) N * map (↑(opLinearEquiv R)) M

Next tactic:
simp_rw [map_le_iff_le_comap]
theorem map_op_mul :
    map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) (M * N) =
      map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) N *
        map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) M := by
  apply le_antisymm
  · simp_rw [map_le_iff_le_comap]
    

Proof state:
case a
ι : Sort uι
R : Type u
inst✝² : CommSemiring R
A : Type v
inst✝¹ : Semiring A
inst✝ : Algebra R A
S T : Set A
M N P Q : Submodule R A
m n : A
⊢ M * N ≤ comap (↑(opLinearEquiv R)) (map (↑(opLinearEquiv R)) N * map (↑(opLinearEquiv R)) M)

Next tactic:
refine' mul_le.2 fun m hm n hn => _
theorem map_op_mul :
    map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) (M * N) =
      map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) N *
        map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) M := by
  apply le_antisymm
  · simp_rw [map_le_iff_le_comap]
    refine' mul_le.2 fun m hm n hn => _
    

Proof state:
case a
ι : Sort uι
R : Type u
inst✝² : CommSemiring R
A : Type v
inst✝¹ : Semiring A
inst✝ : Algebra R A
S T : Set A
M N P Q : Submodule R A
m✝ n✝ m : A
hm : m ∈ M
n : A
hn : n ∈ N
⊢ m * n ∈ comap (↑(opLinearEquiv R)) (map (↑(opLinearEquiv R)) N * map (↑(opLinearEquiv R)) M)

Next tactic:
rw [mem_comap, map_equiv_eq_comap_symm, map_equiv_eq_comap_symm]
theorem map_op_mul :
    map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) (M * N) =
      map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) N *
        map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) M := by
  apply le_antisymm
  · simp_rw [map_le_iff_le_comap]
    refine' mul_le.2 fun m hm n hn => _
    rw [mem_comap, map_equiv_eq_comap_symm, map_equiv_eq_comap_symm]
    

Proof state:
case a
ι : Sort uι
R : Type u
inst✝² : CommSemiring R
A : Type v
inst✝¹ : Semiring A
inst✝ : Algebra R A
S T : Set A
M N P Q : Submodule R A
m✝ n✝ m : A
hm : m ∈ M
n : A
hn : n ∈ N
⊢ ↑(opLinearEquiv R) (m * n) ∈
    comap (↑(LinearEquiv.symm (opLinearEquiv R))) N * comap (↑(LinearEquiv.symm (opLinearEquiv R))) M

Next tactic:
show op n * op m ∈ _
theorem map_op_mul :
    map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) (M * N) =
      map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) N *
        map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) M := by
  apply le_antisymm
  · simp_rw [map_le_iff_le_comap]
    refine' mul_le.2 fun m hm n hn => _
    rw [mem_comap, map_equiv_eq_comap_symm, map_equiv_eq_comap_symm]
    show op n * op m ∈ _
    

Proof state:
case a
ι : Sort uι
R : Type u
inst✝² : CommSemiring R
A : Type v
inst✝¹ : Semiring A
inst✝ : Algebra R A
S T : Set A
M N P Q : Submodule R A
m✝ n✝ m : A
hm : m ∈ M
n : A
hn : n ∈ N
⊢ op n * op m ∈ comap (↑(LinearEquiv.symm (opLinearEquiv R))) N * comap (↑(LinearEquiv.symm (opLinearEquiv R))) M

Next tactic:
exact mul_mem_mul hn hm
theorem map_op_mul :
    map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) (M * N) =
      map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) N *
        map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) M := by
  apply le_antisymm
  · simp_rw [map_le_iff_le_comap]
    refine' mul_le.2 fun m hm n hn => _
    rw [mem_comap, map_equiv_eq_comap_symm, map_equiv_eq_comap_symm]
    show op n * op m ∈ _
    exact mul_mem_mul hn hm
  · 

Proof state:
case a
ι : Sort uι
R : Type u
inst✝² : CommSemiring R
A : Type v
inst✝¹ : Semiring A
inst✝ : Algebra R A
S T : Set A
M N P Q : Submodule R A
m n : A
⊢ map (↑(opLinearEquiv R)) N * map (↑(opLinearEquiv R)) M ≤ map (↑(opLinearEquiv R)) (M * N)

Next tactic:
refine' mul_le.2 (MulOpposite.rec' fun m hm => MulOpposite.rec' fun n hn => _)
theorem map_op_mul :
    map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) (M * N) =
      map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) N *
        map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) M := by
  apply le_antisymm
  · simp_rw [map_le_iff_le_comap]
    refine' mul_le.2 fun m hm n hn => _
    rw [mem_comap, map_equiv_eq_comap_symm, map_equiv_eq_comap_symm]
    show op n * op m ∈ _
    exact mul_mem_mul hn hm
  · refine' mul_le.2 (MulOpposite.rec' fun m hm => MulOpposite.rec' fun n hn => _)
    

Proof state:
case a
ι : Sort uι
R : Type u
inst✝² : CommSemiring R
A : Type v
inst✝¹ : Semiring A
inst✝ : Algebra R A
S T : Set A
M N P Q : Submodule R A
m✝ n✝ m : A
hm : op m ∈ map (↑(opLinearEquiv R)) N
n : A
hn : op n ∈ map (↑(opLinearEquiv R)) M
⊢ op m * op n ∈ map (↑(opLinearEquiv R)) (M * N)

Next tactic:
rw [Submodule.mem_map_equiv] at hm hn ⊢
theorem map_op_mul :
    map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) (M * N) =
      map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) N *
        map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) M := by
  apply le_antisymm
  · simp_rw [map_le_iff_le_comap]
    refine' mul_le.2 fun m hm n hn => _
    rw [mem_comap, map_equiv_eq_comap_symm, map_equiv_eq_comap_symm]
    show op n * op m ∈ _
    exact mul_mem_mul hn hm
  · refine' mul_le.2 (MulOpposite.rec' fun m hm => MulOpposite.rec' fun n hn => _)
    rw [Submodule.mem_map_equiv] at hm hn ⊢
    

Proof state:
case a
ι : Sort uι
R : Type u
inst✝² : CommSemiring R
A : Type v
inst✝¹ : Semiring A
inst✝ : Algebra R A
S T : Set A
M N P Q : Submodule R A
m✝ n✝ m : A
hm : (LinearEquiv.symm (opLinearEquiv R)) (op m) ∈ N
n : A
hn : (LinearEquiv.symm (opLinearEquiv R)) (op n) ∈ M
⊢ (LinearEquiv.symm (opLinearEquiv R)) (op m * op n) ∈ M * N

Next tactic:
exact mul_mem_mul hn hm
theorem comap_unop_mul :
    comap (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ).symm : Aᵐᵒᵖ →ₗ[R] A) (M * N) =
      comap (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ).symm : Aᵐᵒᵖ →ₗ[R] A) N *
        comap (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ).symm : Aᵐᵒᵖ →ₗ[R] A) M := by
  

Proof state:
ι : Sort uι
R : Type u
inst✝² : CommSemiring R
A : Type v
inst✝¹ : Semiring A
inst✝ : Algebra R A
S T : Set A
M N P Q : Submodule R A
m n : A
⊢ comap (↑(LinearEquiv.symm (opLinearEquiv R))) (M * N) =
    comap (↑(LinearEquiv.symm (opLinearEquiv R))) N * comap (↑(LinearEquiv.symm (opLinearEquiv R))) M

Next tactic:
simp_rw [← map_equiv_eq_comap_symm, map_op_mul]
theorem map_unop_mul (M N : Submodule R Aᵐᵒᵖ) :
    map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ).symm : Aᵐᵒᵖ →ₗ[R] A) (M * N) =
      map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ).symm : Aᵐᵒᵖ →ₗ[R] A) N *
        map (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ).symm : Aᵐᵒᵖ →ₗ[R] A) M :=
  have : Function.Injective (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) :=
    LinearEquiv.injective _
  map_injective_of_injective this <| by
    

Proof state:
ι : Sort uι
R : Type u
inst✝² : CommSemiring R
A : Type v
inst✝¹ : Semiring A
inst✝ : Algebra R A
S T : Set A
M✝ N✝ P Q : Submodule R A
m n : A
M N : Submodule R Aᵐᵒᵖ
this : Function.Injective ⇑↑(opLinearEquiv R)
⊢ map (↑(opLinearEquiv R)) (map (↑(LinearEquiv.symm (opLinearEquiv R))) (M * N)) =
    map (↑(opLinearEquiv R))
      (map (↑(LinearEquiv.symm (opLinearEquiv R))) N * map (↑(LinearEquiv.symm (opLinearEquiv R))) M)

Next tactic:
rw [← map_comp, map_op_mul, ← map_comp, ← map_comp, LinearEquiv.comp_coe,
      LinearEquiv.symm_trans_self, LinearEquiv.refl_toLinearMap, map_id, map_id, map_id]
theorem comap_op_mul (M N : Submodule R Aᵐᵒᵖ) :
    comap (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) (M * N) =
      comap (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) N *
        comap (↑(opLinearEquiv R : A ≃ₗ[R] Aᵐᵒᵖ) : A →ₗ[R] Aᵐᵒᵖ) M := by
  

Proof state:
ι : Sort uι
R : Type u
inst✝² : CommSemiring R
A : Type v
inst✝¹ : Semiring A
inst✝ : Algebra R A
S T : Set A
M✝ N✝ P Q : Submodule R A
m n : A
M N : Submodule R Aᵐᵒᵖ
⊢ comap (↑(opLinearEquiv R)) (M * N) = comap (↑(opLinearEquiv R)) N * comap (↑(opLinearEquiv R)) M

Next tactic:
simp_rw [comap_equiv_eq_map_symm, map_unop_mul]
lemma restrictScalars_mul {A B C} [CommSemiring A] [CommSemiring B] [Semiring C]
    [Algebra A B] [Algebra A C] [Algebra B C] [IsScalarTower A B C] {I J : Submodule B C} :
  (I * J).restrictScalars A = I.restrictScalars A * J.restrictScalars A := by
  

Proof state:
ι : Sort uι
R : Type u
inst✝⁹ : CommSemiring R
A✝ : Type v
inst✝⁸ : Semiring A✝
inst✝⁷ : Algebra R A✝
S T : Set A✝
M N P Q : Submodule R A✝
m n : A✝
A : Type u_1
B : Type u_2
C : Type u_3
inst✝⁶ : CommSemiring A
inst✝⁵ : CommSemiring B
inst✝⁴ : Semiring C
inst✝³ : Algebra A B
inst✝² : Algebra A C
inst✝¹ : Algebra B C
inst✝ : IsScalarTower A B C
I J : Submodule B C
⊢ restrictScalars A (I * J) = restrictScalars A I * restrictScalars A J

Next tactic:
apply le_antisymm
lemma restrictScalars_mul {A B C} [CommSemiring A] [CommSemiring B] [Semiring C]
    [Algebra A B] [Algebra A C] [Algebra B C] [IsScalarTower A B C] {I J : Submodule B C} :
  (I * J).restrictScalars A = I.restrictScalars A * J.restrictScalars A := by
  apply le_antisymm
  · 

Proof state:
case a
ι : Sort uι
R : Type u
inst✝⁹ : CommSemiring R
A✝ : Type v
inst✝⁸ : Semiring A✝
inst✝⁷ : Algebra R A✝
S T : Set A✝
M N P Q : Submodule R A✝
m n : A✝
A : Type u_1
B : Type u_2
C : Type u_3
inst✝⁶ : CommSemiring A
inst✝⁵ : CommSemiring B
inst✝⁴ : Semiring C
inst✝³ : Algebra A B
inst✝² : Algebra A C
inst✝¹ : Algebra B C
inst✝ : IsScalarTower A B C
I J : Submodule B C
⊢ restrictScalars A (I * J) ≤ restrictScalars A I * restrictScalars A J

Next tactic:
intro x (hx : x ∈ I * J)
lemma restrictScalars_mul {A B C} [CommSemiring A] [CommSemiring B] [Semiring C]
    [Algebra A B] [Algebra A C] [Algebra B C] [IsScalarTower A B C] {I J : Submodule B C} :
  (I * J).restrictScalars A = I.restrictScalars A * J.restrictScalars A := by
  apply le_antisymm
  · intro x (hx : x ∈ I * J)
    

Proof state:
case a
ι : Sort uι
R : Type u
inst✝⁹ : CommSemiring R
A✝ : Type v
inst✝⁸ : Semiring A✝
inst✝⁷ : Algebra R A✝
S T : Set A✝
M N P Q : Submodule R A✝
m n : A✝
A : Type u_1
B : Type u_2
C : Type u_3
inst✝⁶ : CommSemiring A
inst✝⁵ : CommSemiring B
inst✝⁴ : Semiring C
inst✝³ : Algebra A B
inst✝² : Algebra A C
inst✝¹ : Algebra B C
inst✝ : IsScalarTower A B C
I J : Submodule B C
x : C
hx : x ∈ I * J
⊢ x ∈ restrictScalars A I * restrictScalars A J

Next tactic:
refine Submodule.mul_induction_on hx ?_ ?_
lemma restrictScalars_mul {A B C} [CommSemiring A] [CommSemiring B] [Semiring C]
    [Algebra A B] [Algebra A C] [Algebra B C] [IsScalarTower A B C] {I J : Submodule B C} :
  (I * J).restrictScalars A = I.restrictScalars A * J.restrictScalars A := by
  apply le_antisymm
  · intro x (hx : x ∈ I * J)
    refine Submodule.mul_induction_on hx ?_ ?_
    · 

Proof state:
case a.refine_1
ι : Sort uι
R : Type u
inst✝⁹ : CommSemiring R
A✝ : Type v
inst✝⁸ : Semiring A✝
inst✝⁷ : Algebra R A✝
S T : Set A✝
M N P Q : Submodule R A✝
m n : A✝
A : Type u_1
B : Type u_2
C : Type u_3
inst✝⁶ : CommSemiring A
inst✝⁵ : CommSemiring B
inst✝⁴ : Semiring C
inst✝³ : Algebra A B
inst✝² : Algebra A C
inst✝¹ : Algebra B C
inst✝ : IsScalarTower A B C
I J : Submodule B C
x : C
hx : x ∈ I * J
⊢ ∀ m ∈ I, ∀ n ∈ J, m * n ∈ restrictScalars A I * restrictScalars A J

Next tactic:
exact fun m hm n hn ↦ mul_mem_mul hm hn
lemma restrictScalars_mul {A B C} [CommSemiring A] [CommSemiring B] [Semiring C]
    [Algebra A B] [Algebra A C] [Algebra B C] [IsScalarTower A B C] {I J : Submodule B C} :
  (I * J).restrictScalars A = I.restrictScalars A * J.restrictScalars A := by
  apply le_antisymm
  · intro x (hx : x ∈ I * J)
    refine Submodule.mul_induction_on hx ?_ ?_
    · exact fun m hm n hn ↦ mul_mem_mul hm hn
    · 

Proof state:
case a.refine_2
ι : Sort uι
R : Type u
inst✝⁹ : CommSemiring R
A✝ : Type v
inst✝⁸ : Semiring A✝
inst✝⁷ : Algebra R A✝
S T : Set A✝
M N P Q : Submodule R A✝
m n : A✝
A : Type u_1
B : Type u_2
C : Type u_3
inst✝⁶ : CommSemiring A
inst✝⁵ : CommSemiring B
inst✝⁴ : Semiring C
inst✝³ : Algebra A B
inst✝² : Algebra A C
inst✝¹ : Algebra B C
inst✝ : IsScalarTower A B C
I J : Submodule B C
x : C
hx : x ∈ I * J
⊢ ∀ (x y : C),
    x ∈ restrictScalars A I * restrictScalars A J →
      y ∈ restrictScalars A I * restrictScalars A J → x + y ∈ restrictScalars A I * restrictScalars A J

Next tactic:
exact fun _ _ ↦ add_mem
lemma restrictScalars_mul {A B C} [CommSemiring A] [CommSemiring B] [Semiring C]
    [Algebra A B] [Algebra A C] [Algebra B C] [IsScalarTower A B C] {I J : Submodule B C} :
  (I * J).restrictScalars A = I.restrictScalars A * J.restrictScalars A := by
  apply le_antisymm
  · intro x (hx : x ∈ I * J)
    refine Submodule.mul_induction_on hx ?_ ?_
    · exact fun m hm n hn ↦ mul_mem_mul hm hn
    · exact fun _ _ ↦ add_mem
  · 

Proof state:
case a
ι : Sort uι
R : Type u
inst✝⁹ : CommSemiring R
A✝ : Type v
inst✝⁸ : Semiring A✝
inst✝⁷ : Algebra R A✝
S T : Set A✝
M N P Q : Submodule R A✝
m n : A✝
A : Type u_1
B : Type u_2
C : Type u_3
inst✝⁶ : CommSemiring A
inst✝⁵ : CommSemiring B
inst✝⁴ : Semiring C
inst✝³ : Algebra A B
inst✝² : Algebra A C
inst✝¹ : Algebra B C
inst✝ : IsScalarTower A B C
I J : Submodule B C
⊢ restrictScalars A I * restrictScalars A J ≤ restrictScalars A (I * J)

Next tactic:
exact mul_le.mpr (fun _ hm _ hn ↦ mul_mem_mul hm hn)
theorem mem_span_mul_finite_of_mem_span_mul {R A} [Semiring R] [AddCommMonoid A] [Mul A]
    [Module R A] {S : Set A} {S' : Set A} {x : A} (hx : x ∈ span R (S * S')) :
    ∃ T T' : Finset A, ↑T ⊆ S ∧ ↑T' ⊆ S' ∧ x ∈ span R (T * T' : Set A) := by
  

Proof state:
ι : Sort uι
R✝ : Type u
inst✝⁶ : CommSemiring R✝
A✝ : Type v
inst✝⁵ : Semiring A✝
inst✝⁴ : Algebra R✝ A✝
S✝ T : Set A✝
M N P Q : Submodule R✝ A✝
m n : A✝
R : Type u_1
A : Type u_2
inst✝³ : Semiring R
inst✝² : AddCommMonoid A
inst✝¹ : Mul A
inst✝ : Module R A
S S' : Set A
x : A
hx : x ∈ span R (S * S')
⊢ ∃ T T', ↑T ⊆ S ∧ ↑T' ⊆ S' ∧ x ∈ span R (↑T * ↑T')

Next tactic:
obtain ⟨U, h, hU⟩ := mem_span_finite_of_mem_span hx
theorem mem_span_mul_finite_of_mem_span_mul {R A} [Semiring R] [AddCommMonoid A] [Mul A]
    [Module R A] {S : Set A} {S' : Set A} {x : A} (hx : x ∈ span R (S * S')) :
    ∃ T T' : Finset A, ↑T ⊆ S ∧ ↑T' ⊆ S' ∧ x ∈ span R (T * T' : Set A) := by
  obtain ⟨U, h, hU⟩ := mem_span_finite_of_mem_span hx
  

Proof state:
case intro.intro
ι : Sort uι
R✝ : Type u
inst✝⁶ : CommSemiring R✝
A✝ : Type v
inst✝⁵ : Semiring A✝
inst✝⁴ : Algebra R✝ A✝
S✝ T : Set A✝
M N P Q : Submodule R✝ A✝
m n : A✝
R : Type u_1
A : Type u_2
inst✝³ : Semiring R
inst✝² : AddCommMonoid A
inst✝¹ : Mul A
inst✝ : Module R A
S S' : Set A
x : A
hx : x ∈ span R (S * S')
U : Finset A
h : ↑U ⊆ S * S'
hU : x ∈ span R ↑U
⊢ ∃ T T', ↑T ⊆ S ∧ ↑T' ⊆ S' ∧ x ∈ span R (↑T * ↑T')

Next tactic:
obtain ⟨T, T', hS, hS', h⟩ := Finset.subset_mul h
theorem mem_span_mul_finite_of_mem_span_mul {R A} [Semiring R] [AddCommMonoid A] [Mul A]
    [Module R A] {S : Set A} {S' : Set A} {x : A} (hx : x ∈ span R (S * S')) :
    ∃ T T' : Finset A, ↑T ⊆ S ∧ ↑T' ⊆ S' ∧ x ∈ span R (T * T' : Set A) := by
  obtain ⟨U, h, hU⟩ := mem_span_finite_of_mem_span hx
  obtain ⟨T, T', hS, hS', h⟩ := Finset.subset_mul h
  

Proof state:
case intro.intro.intro.intro.intro.intro
ι : Sort uι
R✝ : Type u
inst✝⁶ : CommSemiring R✝
A✝ : Type v
inst✝⁵ : Semiring A✝
inst✝⁴ : Algebra R✝ A✝
S✝ T✝ : Set A✝
M N P Q : Submodule R✝ A✝
m n : A✝
R : Type u_1
A : Type u_2
inst✝³ : Semiring R
inst✝² : AddCommMonoid A
inst✝¹ : Mul A
inst✝ : Module R A
S S' : Set A
x : A
hx : x ∈ span R (S * S')
U : Finset A
h✝ : ↑U ⊆ S * S'
hU : x ∈ span R ↑U
T T' : Finset A
hS : ↑T ⊆ S
hS' : ↑T' ⊆ S'
h : U ⊆ T * T'
⊢ ∃ T T', ↑T ⊆ S ∧ ↑T' ⊆ S' ∧ x ∈ span R (↑T * ↑T')

Next tactic:
use T, T', hS, hS'
theorem mem_span_mul_finite_of_mem_span_mul {R A} [Semiring R] [AddCommMonoid A] [Mul A]
    [Module R A] {S : Set A} {S' : Set A} {x : A} (hx : x ∈ span R (S * S')) :
    ∃ T T' : Finset A, ↑T ⊆ S ∧ ↑T' ⊆ S' ∧ x ∈ span R (T * T' : Set A) := by
  obtain ⟨U, h, hU⟩ := mem_span_finite_of_mem_span hx
  obtain ⟨T, T', hS, hS', h⟩ := Finset.subset_mul h
  use T, T', hS, hS'
  

Proof state:
case right
ι : Sort uι
R✝ : Type u
inst✝⁶ : CommSemiring R✝
A✝ : Type v
inst✝⁵ : Semiring A✝
inst✝⁴ : Algebra R✝ A✝
S✝ T✝ : Set A✝
M N P Q : Submodule R✝ A✝
m n : A✝
R : Type u_1
A : Type u_2
inst✝³ : Semiring R
inst✝² : AddCommMonoid A
inst✝¹ : Mul A
inst✝ : Module R A
S S' : Set A
x : A
hx : x ∈ span R (S * S')
U : Finset A
h✝ : ↑U ⊆ S * S'
hU : x ∈ span R ↑U
T T' : Finset A
hS : ↑T ⊆ S
hS' : ↑T' ⊆ S'
h : U ⊆ T * T'
⊢ x ∈ span R (↑T * ↑T')

Next tactic:
have h' : (U : Set A) ⊆ T * T' := by assumption_mod_cast
theorem mem_span_mul_finite_of_mem_span_mul {R A} [Semiring R] [AddCommMonoid A] [Mul A]
    [Module R A] {S : Set A} {S' : Set A} {x : A} (hx : x ∈ span R (S * S')) :
    ∃ T T' : Finset A, ↑T ⊆ S ∧ ↑T' ⊆ S' ∧ x ∈ span R (T * T' : Set A) := by
  obtain ⟨U, h, hU⟩ := mem_span_finite_of_mem_span hx
  obtain ⟨T, T', hS, hS', h⟩ := Finset.subset_mul h
  use T, T', hS, hS'
  have h' : (U : Set A) ⊆ T * T' := by 

Proof state:
ι : Sort uι
R✝ : Type u
inst✝⁶ : CommSemiring R✝
A✝ : Type v
inst✝⁵ : Semiring A✝
inst✝⁴ : Algebra R✝ A✝
S✝ T✝ : Set A✝
M N P Q : Submodule R✝ A✝
m n : A✝
R : Type u_1
A : Type u_2
inst✝³ : Semiring R
inst✝² : AddCommMonoid A
inst✝¹ : Mul A
inst✝ : Module R A
S S' : Set A
x : A
hx : x ∈ span R (S * S')
U : Finset A
h✝ : ↑U ⊆ S * S'
hU : x ∈ span R ↑U
T T' : Finset A
hS : ↑T ⊆ S
hS' : ↑T' ⊆ S'
h : U ⊆ T * T'
⊢ ↑U ⊆ ↑T * ↑T'

Next tactic:
assumption_mod_cast
theorem mem_span_mul_finite_of_mem_span_mul {R A} [Semiring R] [AddCommMonoid A] [Mul A]
    [Module R A] {S : Set A} {S' : Set A} {x : A} (hx : x ∈ span R (S * S')) :
    ∃ T T' : Finset A, ↑T ⊆ S ∧ ↑T' ⊆ S' ∧ x ∈ span R (T * T' : Set A) := by
  obtain ⟨U, h, hU⟩ := mem_span_finite_of_mem_span hx
  obtain ⟨T, T', hS, hS', h⟩ := Finset.subset_mul h
  use T, T', hS, hS'
  have h' : (U : Set A) ⊆ T * T' := by assumption_mod_cast
  

Proof state:
case right
ι : Sort uι
R✝ : Type u
inst✝⁶ : CommSemiring R✝
A✝ : Type v
inst✝⁵ : Semiring A✝
inst✝⁴ : Algebra R✝ A✝
S✝ T✝ : Set A✝
M N P Q : Submodule R✝ A✝
m n : A✝
R : Type u_1
A : Type u_2
inst✝³ : Semiring R
inst✝² : AddCommMonoid A
inst✝¹ : Mul A
inst✝ : Module R A
S S' : Set A
x : A
hx : x ∈ span R (S * S')
U : Finset A
h✝ : ↑U ⊆ S * S'
hU : x ∈ span R ↑U
T T' : Finset A
hS : ↑T ⊆ S
hS' : ↑T' ⊆ S'
h : U ⊆ T * T'
h' : ↑U ⊆ ↑T * ↑T'
⊢ x ∈ span R (↑T * ↑T')

Next tactic:
have h'' := span_mono h' hU