Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(LinearAlgebra/BilinearForm/TensorProduct): Tensor products of bilinear maps #14988

Open
wants to merge 66 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
250f937
Make LinearMap.BilinMap.tensorDistrib work for bilinear maps
mans0954 Jul 21, 2024
8476709
Progress
mans0954 Jul 21, 2024
7f4b8b4
Get LinearAlgebra/BilinearForm/TensorProduct to build by commenting s…
mans0954 Jul 21, 2024
3dcc169
Get LinearAlgebra/QuadraticForm/TensorProduct to build by commenting …
mans0954 Jul 21, 2024
8eb13e5
Fix
mans0954 Jul 21, 2024
069ebbd
Add more N
mans0954 Jul 21, 2024
4074a79
Recover BilinForm
mans0954 Jul 22, 2024
2d302a6
Tidy uo
mans0954 Jul 22, 2024
0491c55
Just try to get it building
mans0954 Jul 22, 2024
12e8ccb
Mostly put it back together
mans0954 Jul 22, 2024
7530ddc
Reorg
mans0954 Jul 22, 2024
873d58e
fudge it into building
mans0954 Jul 22, 2024
13cd0ee
Implement LinearMap.BilinMap.congr₂ with LinearEquiv.congrRight
mans0954 Jul 23, 2024
624ba77
Implement LinearMap.BilinForm.congr with LinearEquiv.congrRight and L…
mans0954 Jul 23, 2024
cbbb0a1
Merge branch 'master' into mans0954/tensorDistrib
mans0954 Jul 30, 2024
2a2ff93
Merge branch 'master' into mans0954/tensorDistrib
mans0954 Aug 1, 2024
55c2ad0
Merge branch 'master' into mans0954/tensorDistrib
mans0954 Aug 7, 2024
312d57a
Merge branch 'master' into mans0954/tensorDistrib
mans0954 Aug 9, 2024
03a4d93
Merge branch 'master' into mans0954/tensorDistrib
mans0954 Aug 15, 2024
35779ab
Remove unused vars
mans0954 Aug 15, 2024
0fd0842
Merge branch 'master' into mans0954/tensorDistrib
mans0954 Aug 23, 2024
b1c3526
Merge branch 'master' into mans0954/tensorDistrib
mans0954 Aug 31, 2024
ce17df7
Merge branch 'master' into mans0954/tensorDistrib
mans0954 Sep 7, 2024
e5648a5
Merge branch 'master' into mans0954/tensorDistrib
mans0954 Sep 13, 2024
cdf6efc
Merge branch 'master' into mans0954/tensorDistrib
mans0954 Sep 20, 2024
32fae52
Update Mathlib/LinearAlgebra/QuadraticForm/Basic.lean
mans0954 Oct 2, 2024
f1095a5
Correct doc string
mans0954 Oct 2, 2024
1b97cd7
Remove spurious --
mans0954 Oct 2, 2024
c81a91d
Merge branch 'master' into mans0954/tensorDistrib
mans0954 Oct 2, 2024
da9154a
Add docstrings
mans0954 Oct 3, 2024
5f331f0
Merge branch 'master' into mans0954/tensorDistrib
mans0954 Oct 5, 2024
390c528
deprecate and change name
eric-wieser Oct 5, 2024
85c9ca4
Fix
mans0954 Oct 5, 2024
e032808
QuadraticMap.congr₂
mans0954 Oct 5, 2024
d2ec918
LinearMap.BilinMap.congr₂
mans0954 Oct 5, 2024
3b08310
congr₂_refl and congr₂_symm
mans0954 Oct 5, 2024
d22d812
Rename
mans0954 Oct 5, 2024
02c2c5a
Update Mathlib/LinearAlgebra/QuadraticForm/Basic.lean
mans0954 Oct 5, 2024
1e125a3
Add congr₂ section
mans0954 Oct 6, 2024
6cd85c3
tidy
eric-wieser Oct 6, 2024
6e990d8
fix double-namespace
eric-wieser Oct 6, 2024
14b9754
Merge branch 'mans0954/congr₂' into mans0954/tensorDistrib
mans0954 Oct 6, 2024
5e3d4f1
Merge branch 'master' into mans0954/tensorDistrib
mans0954 Oct 14, 2024
15213e8
Fix
mans0954 Oct 14, 2024
6a8d38b
Gah
mans0954 Oct 14, 2024
c7cd0fa
Merge branch 'master' into mans0954/tensorDistrib
mans0954 Oct 24, 2024
4133bb3
Remove duplicate def
mans0954 Oct 24, 2024
d75ee5b
Dot notation
mans0954 Oct 24, 2024
cd7de90
Update Mathlib/LinearAlgebra/BilinearForm/TensorProduct.lean
mans0954 Oct 25, 2024
3e25ca4
Rename
mans0954 Oct 25, 2024
f88ab45
Merge branch 'master' into mans0954/tensorDistrib
mans0954 Oct 25, 2024
6f0e4a2
Remove old docstring
mans0954 Oct 25, 2024
ededa78
Remove old docstring
mans0954 Oct 25, 2024
de32035
Update comment
mans0954 Oct 25, 2024
1677ddc
Fix
mans0954 Oct 25, 2024
18b17e9
Simplify
mans0954 Oct 25, 2024
7823fa3
Update Mathlib/LinearAlgebra/BilinearForm/TensorProduct.lean
mans0954 Oct 26, 2024
0402b30
Try new QuadraticForm.tensorDistrib def
mans0954 Oct 26, 2024
90ed818
Patch it back together
mans0954 Oct 26, 2024
a67361e
Remove unused argument
mans0954 Oct 26, 2024
1ebaabd
Improve
mans0954 Oct 26, 2024
ab07599
Remove alternative def
mans0954 Oct 26, 2024
2e3f587
BilinMap versions of baseChange and baseChange_tmul
mans0954 Oct 26, 2024
336fee8
Merge branch 'master' into mans0954/tensorDistrib
mans0954 Oct 27, 2024
7900d62
Add explanitory note
mans0954 Oct 28, 2024
21ea33a
Move comment
mans0954 Oct 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions Mathlib/LinearAlgebra/BilinearForm/Hom.lean
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Bilinear form,
-/

open LinearMap (BilinForm)
open LinearMap (BilinMap)

universe u v w

Expand Down Expand Up @@ -305,6 +306,25 @@ theorem comp_congr (e : M' ≃ₗ[R] M'') (B : BilinForm R M) (l r : M' →ₗ[R
B.comp (l.comp (e.symm : M'' →ₗ[R] M')) (r.comp (e.symm : M'' →ₗ[R] M')) :=
rfl

variable {N₁ N₂ : Type*}
variable [AddCommMonoid N₁] [AddCommMonoid N₂] [Module R N₁] [Module R N₂]

/-- When `N₁` and `N₂` are equivalent, bilinear maps on `M` into `N₁` are equivalent to bilinear
maps into `N₂`. -/
@[simps]
def _root_.LinearMap.BilinMap.congr₂ (e : N₁ ≃ₗ[R] N₂) : BilinMap R M N₁ ≃ₗ[R] BilinMap R M N₂ where
mans0954 marked this conversation as resolved.
Show resolved Hide resolved
toFun B := LinearMap.compr₂ B e
invFun B := LinearMap.compr₂ B e.symm
left_inv B := ext₂ fun x => by
simp only [compr₂_apply, LinearEquiv.coe_coe, LinearEquiv.symm_apply_apply, implies_true]
right_inv B := ext₂ fun x => by
simp only [compr₂_apply, LinearEquiv.coe_coe, LinearEquiv.apply_symm_apply, implies_true]
map_add' B B' := ext₂ fun x y => by
simp only [compr₂_apply, LinearMap.add_apply, map_add, LinearEquiv.coe_coe]
map_smul' B B' := ext₂ fun x y => by
simp only [compr₂_apply, smul_apply, LinearMapClass.map_smul, LinearEquiv.coe_coe,
RingHom.id_apply]

end congr

section LinMulLin
Expand Down
49 changes: 38 additions & 11 deletions Mathlib/LinearAlgebra/BilinearForm/TensorProduct.lean
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Authors: Eric Wieser
-/
import Mathlib.LinearAlgebra.Dual
import Mathlib.LinearAlgebra.TensorProduct.Tower
import Mathlib.LinearAlgebra.BilinearForm.Hom

/-!
# The bilinear form on a tensor product
Expand All @@ -20,9 +21,10 @@ import Mathlib.LinearAlgebra.TensorProduct.Tower

suppress_compilation

universe u v w uι uR uA uM₁ uM₂
universe u v w uι uR uA uM₁ uM₂ uN₁ uN₂

variable {ι : Type uι} {R : Type uR} {A : Type uA} {M₁ : Type uM₁} {M₂ : Type uM₂}
variable {ι : Type uι} {R : Type uR} {A : Type uA} {M₁ : Type uM₁} {M₂ : Type uM₂} {N₁ : Type uN₁}
{N₂ : Type uN₂}

open TensorProduct

Expand All @@ -35,23 +37,48 @@ open LinearMap (BilinForm)

section CommSemiring
variable [CommSemiring R] [CommSemiring A]
variable [AddCommMonoid M₁] [AddCommMonoid M₂]
variable [Algebra R A] [Module R M₁] [Module A M₁]
variable [AddCommMonoid M₁] [AddCommMonoid M₂] [AddCommMonoid N₁] [AddCommMonoid N₂]
variable [Algebra R A] [Module R M₁] [Module A M₁] [Module R N₁] [Module A N₁]
variable [SMulCommClass R A M₁] [SMulCommClass A R M₁] [IsScalarTower R A M₁]
variable [Module R M₂]
variable [SMulCommClass R A N₁] [SMulCommClass A R N₁] [IsScalarTower R A N₁]
variable [Module R M₂] [Module R N₂]

variable (R A) in
/-- The tensor product of two bilinear maps injects into bilinear maps on tensor products.

Note this is heterobasic; the bilinear map on the left can take values in a module over a
(commutative) algebra over the ring of the module in which the right bilinear map is valued. -/
def tensorDistrib' :
mans0954 marked this conversation as resolved.
Show resolved Hide resolved
((BilinMap A M₁ N₁) ⊗[R] (BilinMap R M₂ N₂)) →ₗ[A] ((BilinMap A (M₁ ⊗[R] M₂) (N₁ ⊗[R] N₂))) :=
mans0954 marked this conversation as resolved.
Show resolved Hide resolved
(TensorProduct.lift.equiv A (M₁ ⊗[R] M₂) (M₁ ⊗[R] M₂) (N₁ ⊗[R] N₂)).symm.toLinearMap ∘ₗ
((LinearMap.llcomp A _ _ _).flip
(TensorProduct.AlgebraTensorModule.tensorTensorTensorComm R A M₁ M₂ M₁ M₂).toLinearMap)
∘ₗ TensorProduct.AlgebraTensorModule.homTensorHomMap R _ _ _ _ _ _
∘ₗ (TensorProduct.AlgebraTensorModule.congr
(TensorProduct.lift.equiv A M₁ M₁ N₁)
(TensorProduct.lift.equiv R _ _ _)).toLinearMap

@[simp]
theorem tensorDistrib_tmul' (B₁ : BilinMap A M₁ N₁) (B₂ : BilinMap R M₂ N₂) (m₁ : M₁) (m₂ : M₂)
(m₁' : M₁) (m₂' : M₂) :
tensorDistrib' R A (B₁ ⊗ₜ B₂) (m₁ ⊗ₜ m₂) (m₁' ⊗ₜ m₂')
= B₁ m₁ m₁' ⊗ₜ B₂ m₂ m₂' :=
rfl

/-- The tensor product of two bilinear forms, a shorthand for dot notation. -/
protected abbrev tmul' (B₁ : BilinMap A M₁ N₁) (B₂ : BilinMap R M₂ N₂) :
BilinMap A (M₁ ⊗[R] M₂) (N₁ ⊗[R] N₂) :=
tensorDistrib' R A (B₁ ⊗ₜ[R] B₂)

variable (R A) in
/-- The tensor product of two bilinear forms injects into bilinear forms on tensor products.

Note this is heterobasic; the bilinear form on the left can take values in an (commutative) algebra
over the ring in which the right bilinear form is valued. -/
def tensorDistrib : BilinForm A M₁ ⊗[R] BilinForm R M₂ →ₗ[A] BilinForm A (M₁ ⊗[R] M₂) :=
((TensorProduct.AlgebraTensorModule.tensorTensorTensorComm R A M₁ M₂ M₁ M₂).dualMap
≪≫ₗ (TensorProduct.lift.equiv A (M₁ ⊗[R] M₂) (M₁ ⊗[R] M₂) A).symm).toLinearMap
∘ₗ TensorProduct.AlgebraTensorModule.dualDistrib R _ _ _
∘ₗ (TensorProduct.AlgebraTensorModule.congr
(TensorProduct.lift.equiv A M₁ M₁ A)
(TensorProduct.lift.equiv R _ _ _)).toLinearMap
(congr₂ (AlgebraTensorModule.rid R A A)).toLinearMap ∘ₗ (tensorDistrib' R A)

variable (R A) in

-- TODO: make the RHS `MulOpposite.op (B₂ m₂ m₂') • B₁ m₁ m₁'` so that this has a nicer defeq for
-- `R = A` of `B₁ m₁ m₁' * B₂ m₂ m₂'`, as it did before the generalization in #6306.
Expand Down
27 changes: 22 additions & 5 deletions Mathlib/LinearAlgebra/QuadraticForm/Basic.lean
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,23 @@ def _root_.LinearMap.compQuadraticMap' [CommSemiring S] [Algebra S R] [Module S
(f : N →ₗ[S] P) (Q : QuadraticMap R M N) : QuadraticMap S M P :=
_root_.LinearMap.compQuadraticMap f Q.restrictScalars


/-- When `N₁` and `N₂` are equivalent, bilinear maps on `M` into `N₁` are equivalent to bilinear
mans0954 marked this conversation as resolved.
Show resolved Hide resolved
maps into `N₂`. -/
@[simps]
def congr₂ (e : N ≃ₗ[R] P) : QuadraticMap R M N ≃ₗ[R] QuadraticMap R M P where
toFun Q := e.compQuadraticMap Q
invFun Q := e.symm.compQuadraticMap Q
left_inv _ := ext fun x => by
simp only [LinearMap.compQuadraticMap_apply, LinearEquiv.coe_coe, LinearEquiv.symm_apply_apply]
right_inv _ := ext fun x => by
simp only [LinearMap.compQuadraticMap_apply, LinearEquiv.coe_coe, LinearEquiv.apply_symm_apply]
map_add' _ _ := ext fun x => by
simp only [LinearMap.compQuadraticMap_apply, add_apply, map_add, LinearEquiv.coe_coe]
map_smul' _ _ := ext fun x => by
simp only [LinearMap.compQuadraticMap_apply, smul_apply, LinearMapClass.map_smul,
LinearEquiv.coe_coe, RingHom.id_apply]

end Comp
section NonUnitalNonAssocSemiring

Expand Down Expand Up @@ -874,12 +891,12 @@ theorem toQuadraticMap_associated : (associatedHom S Q).toQuadraticMap = Q :=
-- note: usually `rightInverse` lemmas are named the other way around, but this is consistent
-- with historical naming in this file.
theorem associated_rightInverse :
Function.RightInverse (associatedHom S) (BilinMap.toQuadraticMap : _ → QuadraticMap R M R) :=
Function.RightInverse (associatedHom S) (BilinMap.toQuadraticMap : _ → QuadraticMap R M N) :=
fun Q => toQuadraticMap_associated S Q

/-- `associated'` is the `ℤ`-linear map that sends a quadratic form on a module `M` over `R` to its
associated symmetric bilinear form. -/
abbrev associated' : QuadraticMap R M R →ₗ[ℤ] BilinMap R M R :=
abbrev associated' : QuadraticMap R M N →ₗ[ℤ] BilinMap R M N :=
associatedHom ℤ

/-- Symmetric bilinear forms can be lifted to quadratic forms -/
Expand All @@ -889,9 +906,9 @@ instance canLift :

/-- There exists a non-null vector with respect to any quadratic form `Q` whose associated
bilinear form is non-zero, i.e. there exists `x` such that `Q x ≠ 0`. -/
theorem exists_quadraticForm_ne_zero {Q : QuadraticForm R M}
theorem exists_quadraticForm_ne_zero {Q : QuadraticMap R M N}
-- Porting note: added implicit argument
(hB₁ : associated' (R := R) Q ≠ 0) :
(hB₁ : associated' (R := R) (N := N) Q ≠ 0) :
∃ x, Q x ≠ 0 := by
rw [← not_forall]
intro h
Expand Down Expand Up @@ -1024,7 +1041,7 @@ variable [CommRing R] [AddCommGroup M] [Module R M]
theorem separatingLeft_of_anisotropic [Invertible (2 : R)] (Q : QuadraticMap R M R)
(hB : Q.Anisotropic) :
-- Porting note: added implicit argument
(QuadraticMap.associated' (R := R) Q).SeparatingLeft := fun x hx ↦ hB _ <| by
(QuadraticMap.associated' (R := R) (N := R) Q).SeparatingLeft := fun x hx ↦ hB _ <| by
rw [← hx x]
exact (associated_eq_self_apply _ _ x).symm

Expand Down
46 changes: 40 additions & 6 deletions Mathlib/LinearAlgebra/QuadraticForm/TensorProduct.lean
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ import Mathlib.LinearAlgebra.QuadraticForm.Basic

-/

universe uR uA uM₁ uM₂
universe uR uA uM₁ uM₂ uN₁ uN₂

variable {R : Type uR} {A : Type uA} {M₁ : Type uM₁} {M₂ : Type uM₂}
variable {R : Type uR} {A : Type uA} {M₁ : Type uM₁} {M₂ : Type uM₂} {N₁ : Type uN₁} {N₂ : Type uN₂}

open TensorProduct
open LinearMap (BilinMap)
Expand All @@ -29,18 +29,51 @@ namespace QuadraticForm

section CommRing
variable [CommRing R] [CommRing A]
variable [AddCommGroup M₁] [AddCommGroup M₂]
variable [Algebra R A] [Module R M₁] [Module A M₁]
variable [AddCommGroup M₁] [AddCommGroup M₂] [AddCommGroup N₁] [AddCommGroup N₂]
variable [Algebra R A] [Module R M₁] [Module A M₁] [Module R N₁] [Module A N₁]
variable [SMulCommClass R A M₁] [SMulCommClass A R M₁] [IsScalarTower R A M₁]
variable [Module R M₂] [Invertible (2 : R)]
variable [SMulCommClass R A N₁] [SMulCommClass A R N₁] [IsScalarTower R A N₁]
variable [Module R M₂] [Module R N₂] [Invertible (2 : R)]

variable (R A) in
/-- The tensor product of two quadratic maps injects into quadratic maps on tensor products.

Note this is heterobasic; the quadratic map on the left can take values in a module over a larger
ring than the one on the right. -/
-- `noncomputable` is a performance workaround for mathlib4#7103
noncomputable def tensorDistrib' :
QuadraticMap A M₁ N₁ ⊗[R] QuadraticMap R M₂ N₂ →ₗ[A] QuadraticMap A (M₁ ⊗[R] M₂) (N₁ ⊗[R] N₂) :=
letI : Invertible (2 : A) := (Invertible.map (algebraMap R A) 2).copy 2 (map_ofNat _ _).symm
-- while `letI`s would produce a better term than `let`, they would make this already-slow
-- definition even slower.
let toQ := BilinMap.toQuadraticMapLinearMap A A (M₁ ⊗[R] M₂)
let tmulB := BilinMap.tensorDistrib' R A (M₁ := M₁) (M₂ := M₂)
let toB := AlgebraTensorModule.map
(QuadraticMap.associated : QuadraticMap A M₁ N₁ →ₗ[A] BilinMap A M₁ N₁)
(QuadraticMap.associated : QuadraticMap R M₂ N₂ →ₗ[R] BilinMap R M₂ N₂)
toQ ∘ₗ tmulB ∘ₗ toB

@[simp]
theorem tensorDistrib_tmul' (Q₁ : QuadraticMap A M₁ N₁) (Q₂ : QuadraticMap R M₂ N₂) (m₁ : M₁)
(m₂ : M₂) : tensorDistrib' R A (Q₁ ⊗ₜ Q₂) (m₁ ⊗ₜ m₂) = Q₁ m₁ ⊗ₜ Q₂ m₂ :=
letI : Invertible (2 : A) := (Invertible.map (algebraMap R A) 2).copy 2 (map_ofNat _ _).symm
(BilinMap.tensorDistrib_tmul' _ _ _ _ _ _).trans <| congr_arg₂ _
(associated_eq_self_apply _ _ _) (associated_eq_self_apply _ _ _)

/-- The tensor product of two quadratic maps, a shorthand for dot notation. -/
-- `noncomputable` is a performance workaround for mathlib4#7103
protected noncomputable abbrev _root_.QuadraticMap.tmul' (Q₁ : QuadraticMap A M₁ N₁)
(Q₂ : QuadraticMap R M₂ N₂) : QuadraticMap A (M₁ ⊗[R] M₂) (N₁ ⊗[R] N₂) :=
tensorDistrib' R A (Q₁ ⊗ₜ[R] Q₂)

variable (R A) in
/-- The tensor product of two quadratic forms injects into quadratic forms on tensor products.

Note this is heterobasic; the quadratic form on the left can take values in a larger ring than
the one on the right. -/
-- `noncomputable` is a performance workaround for mathlib4#7103
-- Should be `(congr₂ (AlgebraTensorModule.rid R A A)).toLinearMap ∘ₗ (tensorDistrib' R A)` but then
-- `associated_tmul` breaks
noncomputable def tensorDistrib :
QuadraticForm A M₁ ⊗[R] QuadraticForm R M₂ →ₗ[A] QuadraticForm A (M₁ ⊗[R] M₂) :=
letI : Invertible (2 : A) := (Invertible.map (algebraMap R A) 2).copy 2 (map_ofNat _ _).symm
Expand All @@ -52,14 +85,15 @@ noncomputable def tensorDistrib :
(QuadraticMap.associated : QuadraticForm A M₁ →ₗ[A] BilinForm A M₁)
(QuadraticMap.associated : QuadraticForm R M₂ →ₗ[R] BilinForm R M₂)
toQ ∘ₗ tmulB ∘ₗ toB
--
mans0954 marked this conversation as resolved.
Show resolved Hide resolved

-- TODO: make the RHS `MulOpposite.op (Q₂ m₂) • Q₁ m₁` so that this has a nicer defeq for
-- `R = A` of `Q₁ m₁ * Q₂ m₂`.
@[simp]
theorem tensorDistrib_tmul (Q₁ : QuadraticForm A M₁) (Q₂ : QuadraticForm R M₂) (m₁ : M₁) (m₂ : M₂) :
tensorDistrib R A (Q₁ ⊗ₜ Q₂) (m₁ ⊗ₜ m₂) = Q₂ m₂ • Q₁ m₁ :=
letI : Invertible (2 : A) := (Invertible.map (algebraMap R A) 2).copy 2 (map_ofNat _ _).symm
(BilinMap.tensorDistrib_tmul _ _ _ _ _ _).trans <| congr_arg₂ _
(BilinMap.tensorDistrib_tmul _ _ _ _ _ _ _ _).trans <| congr_arg₂ _
(associated_eq_self_apply _ _ _) (associated_eq_self_apply _ _ _)

/-- The tensor product of two quadratic forms, a shorthand for dot notation. -/
Expand Down
Loading