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

[Merged by Bors] - feat: heterogenize TensorProduct.congr and friends #6035

Closed
wants to merge 17 commits into from

Conversation

eric-wieser
Copy link
Member

@eric-wieser eric-wieser commented Jul 20, 2023

The summary is that this PR:

  • generalizes a handful of results to non-commutative algebras (simply by moving them to an earlier section)
  • adds heterogenous versions of map, congr, mapBilinear, homTensorHom, leftComm, tensorTensorTensorComm
  • generalizes lcurry, uncurry, and assoc to take an extra algebra, such that the As in the two different places can separately be replaced with R

The punchline here is really:

def tensorTensorTensorComm :
  (M ⊗[R] N) ⊗[A] (P ⊗[R] Q) ≃ₗ[A] (M ⊗[A] P) ⊗[R] (N ⊗[R] Q) :=

which is valuable for a base change / tensor product of bilinear forms when instantiated as

(M ⊗[R] N) ⊗[A] (Dual A M ⊗[R] Dual R N)
  ≃ₗ[A]
(M ⊗[A] Dual A M) ⊗[R] (N ⊗[R] Dual R N)

It would not surprise me if it's possible to introduce a third ring into tensorTensorTensorComm, but for now I'd prefer to assume that for that particular definition, two rings is enough for anybody!

Unfortunately, this was not the case for lcurry, uncurry, and assoc, which really do need to work over three rings so that the As in the two different places can separately be replaced with R; both permutations are needed in the construction of tensorTensorTensorComm, and it seemed preferable to not have a plethora of primed variants.

I make no claim that the pile of IsScalarTower and SMulCommClass arguments here are in any sense optimal, besides the fact they specifically enable the use-case I have for the base change of bilinear forms.


Open in Gitpod

Extracted from pygae/lean-ga#31. There is more I want to extract from that patch (most notably the heterobasic BilinForm.tensorDistrib, but the rest will come in a future PR.

@leanprover-community-mathlib4-bot leanprover-community-mathlib4-bot added blocked-by-other-PR This PR depends on another PR to Mathlib (this label is automatically managed by a bot) and removed blocked-by-other-PR This PR depends on another PR to Mathlib (this label is automatically managed by a bot) labels Jul 21, 2023
@leanprover-community-mathlib4-bot leanprover-community-mathlib4-bot added the blocked-by-other-PR This PR depends on another PR to Mathlib (this label is automatically managed by a bot) label Jul 24, 2023
@kim-em kim-em removed the after-port label Jul 25, 2023
@leanprover-community-mathlib4-bot leanprover-community-mathlib4-bot removed the blocked-by-other-PR This PR depends on another PR to Mathlib (this label is automatically managed by a bot) label Jul 27, 2023
@leanprover-community-mathlib4-bot leanprover-community-mathlib4-bot added the blocked-by-other-PR This PR depends on another PR to Mathlib (this label is automatically managed by a bot) label Jul 27, 2023
bors bot pushed a commit that referenced this pull request Jul 27, 2023
There is a reasonably-sized section on modules over two rings before we actual reach tensor products of rings.

The motivation for splitting here is to make room for the results in #6035.

The declarations are copied without modification, the module docstring has been adapted.
@leanprover-community-mathlib4-bot leanprover-community-mathlib4-bot removed the blocked-by-other-PR This PR depends on another PR to Mathlib (this label is automatically managed by a bot) label Jul 28, 2023
@leanprover-community-mathlib4-bot leanprover-community-mathlib4-bot added the merge-conflict The PR has a merge conflict with master, and needs manual merging. (this label is managed by a bot) label Jul 28, 2023
@eric-wieser eric-wieser removed the merge-conflict The PR has a merge conflict with master, and needs manual merging. (this label is managed by a bot) label Jul 28, 2023
adomani pushed a commit that referenced this pull request Jul 28, 2023
There is a reasonably-sized section on modules over two rings before we actual reach tensor products of rings.

The motivation for splitting here is to make room for the results in #6035.

The declarations are copied without modification, the module docstring has been adapted.
@eric-wieser eric-wieser requested a review from jcommelin July 31, 2023 17:14
Copy link
Member

@kbuzzard kbuzzard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get the impression that this work is a lot more impressive than it lets on: I tried mildly generalising some of the results and immediately got into all sorts of problems. All the proofs are very succinct and to be quite frank I think I might struggle with some of them on paper; if everything is R-linear and tensor products are all over R then everything is easy, but once you start throwing around more rings then things seem to become a lot more delicate. Well done! I left a host of comments, some of which don't need acting on and can just be resolved after you've read them if you agree that nothing needs doing. Thanks a lot!

variable (R A B M N P Q)

/-- Heterobasic version of `TensorProduct.map_bilinear` -/
def mapBilinear : (M →ₗ[A] P) →ₗ[B] (N →ₗ[R] Q) →ₗ[R] (M ⊗[R] N →ₗ[A] P ⊗[R] Q) :=
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a candidate for @[simps]? I'm only just getting the hang of @[simps]. Or is the idea that you're safer writing your own simp lemmas for declarations as complicated as this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

simps generates something with implicit type arguments, which aren't really needed here; though I'll admit I don't remember if that was my reason.

In generaly my rule is "use simps if I'm feeling lazy, write the lemma manually if I'm feeling picky or simps screws up". The important thing is to have some simp lemma, the API doesn't really care whether it's generated with simps.

/-- Heterobasic version of `TensorProduct.assoc`:

Linear equivalence between `(M ⊗[A] N) ⊗[R] P` and `M ⊗[A] (N ⊗[R] P)`. -/
def assoc : (M ⊗[A] P) ⊗[R] N ≃ₗ[A] M ⊗[A] P ⊗[R] N :=
def assoc : (M ⊗[A] P) ⊗[R] Q ≃ₗ[B] M ⊗[A] (P ⊗[R] Q) :=
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think there's a version of this where [IsScalarTower A B M] is replaced by [IsScalarTower A B P]? Note that I'm not suggesting that you add it, but if you think that there's some merit to this suggestion then you could leave a comment. This seems to be the only def where you need to assume B is an A-algebra.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know. This was one where the "obvious" implementation required more typeclasses than the statement. I think I recall places in mathlib where the "clever" bundling approach requires more typeclasses than the dumb but annoying induction approach, but I was pretty maximally annoyed by this point and didn't want to think much more about generalization!

@eric-wieser
Copy link
Member Author

eric-wieser commented Aug 2, 2023

I get the impression that this work is a lot more impressive than it lets on: I tried mildly generalising some of the results and immediately got into all sorts of problems.

I'll try to reflect this in an update to the PR description :)

All the proofs are very succinct and to be quite frank I think I might struggle with some of them on paper; if everything is R-linear and tensor products are all over R then everything is easy, but once you start throwing around more rings then things seem to become a lot more delicate.

Frankly tensorTensorTensorComm was awful; keeping track of 4 modules tensored over 3 rings was too much for my working memory, and I think I would have had a much easier time if I could have color-coded the goal view somehow to keep track of them.

Copy link
Member

@jcommelin jcommelin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this looks very clean.
I did not think at all about whether/how this could possibly be generalized. As you indicate, it is probably possible. But we can do that when we need it.

bors merge

@leanprover-community-mathlib4-bot leanprover-community-mathlib4-bot added ready-to-merge This PR has been sent to bors. and removed awaiting-review labels Aug 7, 2023
bors bot pushed a commit that referenced this pull request Aug 7, 2023
The summary is that this PR:
* generalizes a handful of results to non-commutative algebras (simply by moving them to an earlier section)
* adds heterogenous versions of `map`, `congr`, `mapBilinear`, `homTensorHom`, `leftComm`, `tensorTensorTensorComm`
* generalizes `lcurry`, `uncurry`, and `assoc` to take an extra algebra, such that the `A`s in the two different places can separately be replaced with `R`

The punchline here is really:
```lean
def tensorTensorTensorComm :
  (M ⊗[R] N) ⊗[A] (P ⊗[R] Q) ≃ₗ[A] (M ⊗[A] P) ⊗[R] (N ⊗[R] Q) :=
```
which is valuable for a base change / tensor product of bilinear forms when instantiated as
```lean
(M ⊗[R] N) ⊗[A] (Dual A M ⊗[R] Dual R N)
  ≃ₗ[A]
(M ⊗[A] Dual A M) ⊗[R] (N ⊗[R] Dual R N)
```
It would not surprise me if it's possible to introduce a third ring into `tensorTensorTensorComm`, but for now I'd prefer to assume that for that particular definition, two rings is enough for anybody!

Unfortunately, this was not the case for `lcurry`, `uncurry`, and `assoc`, which really do need to work over three rings so that the `A`s in the two different places can separately be replaced with `R`; both permutations are needed in the construction of `tensorTensorTensorComm`, and it seemed preferable to not have a plethora of primed variants.

I make no claim that the pile of `IsScalarTower` and `SMulCommClass` arguments here are in any sense optimal, besides the fact they specifically enable the use-case I have for the base change of bilinear forms.
@bors
Copy link

bors bot commented Aug 7, 2023

Pull request successfully merged into master.

Build succeeded!

The publicly hosted instance of bors-ng is deprecated and will go away soon.

If you want to self-host your own instance, instructions are here.
For more help, visit the forum.

If you want to switch to GitHub's built-in merge queue, visit their help page.

@bors bors bot changed the title feat: heterogenize TensorProduct.congr and friends [Merged by Bors] - feat: heterogenize TensorProduct.congr and friends Aug 7, 2023
@bors bors bot closed this Aug 7, 2023
@bors bors bot deleted the eric-wieser/heterobasic-TensorProduct.congr branch August 7, 2023 05:07
kim-em pushed a commit that referenced this pull request Aug 14, 2023
There is a reasonably-sized section on modules over two rings before we actual reach tensor products of rings.

The motivation for splitting here is to make room for the results in #6035.

The declarations are copied without modification, the module docstring has been adapted.
kim-em pushed a commit that referenced this pull request Aug 14, 2023
The summary is that this PR:
* generalizes a handful of results to non-commutative algebras (simply by moving them to an earlier section)
* adds heterogenous versions of `map`, `congr`, `mapBilinear`, `homTensorHom`, `leftComm`, `tensorTensorTensorComm`
* generalizes `lcurry`, `uncurry`, and `assoc` to take an extra algebra, such that the `A`s in the two different places can separately be replaced with `R`

The punchline here is really:
```lean
def tensorTensorTensorComm :
  (M ⊗[R] N) ⊗[A] (P ⊗[R] Q) ≃ₗ[A] (M ⊗[A] P) ⊗[R] (N ⊗[R] Q) :=
```
which is valuable for a base change / tensor product of bilinear forms when instantiated as
```lean
(M ⊗[R] N) ⊗[A] (Dual A M ⊗[R] Dual R N)
  ≃ₗ[A]
(M ⊗[A] Dual A M) ⊗[R] (N ⊗[R] Dual R N)
```
It would not surprise me if it's possible to introduce a third ring into `tensorTensorTensorComm`, but for now I'd prefer to assume that for that particular definition, two rings is enough for anybody!

Unfortunately, this was not the case for `lcurry`, `uncurry`, and `assoc`, which really do need to work over three rings so that the `A`s in the two different places can separately be replaced with `R`; both permutations are needed in the construction of `tensorTensorTensorComm`, and it seemed preferable to not have a plethora of primed variants.

I make no claim that the pile of `IsScalarTower` and `SMulCommClass` arguments here are in any sense optimal, besides the fact they specifically enable the use-case I have for the base change of bilinear forms.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ready-to-merge This PR has been sent to bors. t-algebra Algebra (groups, rings, fields, etc)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants