Skip to content

[Merged by Bors] - feat(Algebra/Module/Submodule): Symmetric submodules are modular elements in the lattice of submodules over a semiring#36689

Closed
martinwintermath wants to merge 11 commits intoleanprover-community:masterfrom
martinwintermath:submodule-modular-element
Closed

[Merged by Bors] - feat(Algebra/Module/Submodule): Symmetric submodules are modular elements in the lattice of submodules over a semiring#36689
martinwintermath wants to merge 11 commits intoleanprover-community:masterfrom
martinwintermath:submodule-modular-element

Conversation

@martinwintermath
Copy link
Copy Markdown
Contributor

@martinwintermath martinwintermath commented Mar 15, 2026

Add two lemmas that are replacements for modularity on the lattice of submodules that are not necessarily over a ring, but a semiring:

  • sup_inf_assoc_of_le_of_neg_le: if s ≤ p and -s ≤ p then (s ⊔ t) ⊓ p = s ⊔ (t ⊓ p)
  • inf_sup_assoc_of_le_of_neg_le: if p ≤ s and -p ≤ s then (s ⊓ t) ⊔ p = s ⊓ (t ⊔ p)

This allows to shorten the proof that the lattice of submodules over a ring is modular.

I also add specialized versions for cones.


Open in Gitpod

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 15, 2026

PR summary fa6418a815

Import changes for modified files

No significant changes to the import graph

Import changes for all files
Files Import difference

Declarations diff

+ inf_sup_assoc_of_le_of_neg_le
+ inf_sup_assoc_of_le_of_submodule_le
+ instance : IsModularLattice (Submodule R M) := ⟨fun x _ hxy _ _ => by
+ sup_inf_assoc_of_le_of_neg_le
+ sup_inf_assoc_of_le_submodule
- instance : IsModularLattice (Submodule R M)

You can run this locally as follows
## summary with just the declaration names:
./scripts/pr_summary/declarations_diff.sh <optional_commit>

## more verbose report:
./scripts/pr_summary/declarations_diff.sh long <optional_commit>

The doc-module for scripts/pr_summary/declarations_diff.sh contains some details about this script.


No changes to technical debt.

You can run this locally as

./scripts/reporting/technical-debt-metrics.sh pr_summary
  • The relative value is the weighted sum of the differences with weight given by the inverse of the current value of the statistic.
  • The absolute value is the relative value divided by the total sum of the inverses of the current values (i.e. the weighted average of the differences).

@github-actions github-actions bot added the t-algebra Algebra (groups, rings, fields, etc) label Mar 15, 2026
@martinwintermath martinwintermath marked this pull request as ready for review March 15, 2026 18:15
@dagurtomas dagurtomas removed their assignment Mar 26, 2026
Copy link
Copy Markdown
Contributor

@ocfnash ocfnash left a comment

Choose a reason for hiding this comment

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

I made two inline comments below but I now realise there is a bigger issue here: I think the restriction of scalars is a red herring. The thing that makes p behave in the modular fashion is that it is closed under negation.

So I think the following is a better statement:

variable (S : Type*) {M : Type*} [AddCommGroup M] [Semiring S] [Module S M]

lemma sup_inf_assoc_of_forall_neg_mem {s : Submodule S M} (t : Submodule S M)
    {p : Submodule S M} (hp : ∀ x, x ∈ p ↔ -x ∈ p) (hsp : s ≤ p) :
    (s ⊔ t) ⊓ p = s ⊔ (t ⊓ p) := by

This in turn raises a bigger question: should we have a dedicated subobject for such submodules? Probably not but it might be worth a little thought.

@ocfnash ocfnash added the awaiting-author A reviewer has asked the author a question or requested changes. label Mar 31, 2026
@martinwintermath
Copy link
Copy Markdown
Contributor Author

martinwintermath commented Mar 31, 2026

I think the restriction of scalars is a red herring.

It is precisely the version that we need for convex cones, which are implemented as Submodule R≥0 M. There it is important that "closed under negation" can be inferred automatically from [Ring R].
I could implement yours as a second version. Or I could specialize the restrictScalars version to cones-only and move it to the convex cone files (which is what I had initially anyway, but then I generalized).

Regarding dedicated subobject: I played with the idea of a "generalized submodule", something like Submodule R M but in a Module S M, where S is a restriction of R. Currently cones are positive-scalar submodules of an ambient space Module R M. But one could think if them as their own spaces as well. And then it would be neat to still have "R-submodules" for them, like PointedCone.lineal.

There also is AddSubmonoid.support. Maybe relevant.

@ocfnash
Copy link
Copy Markdown
Contributor

ocfnash commented Apr 1, 2026

Even though in your application there are two sets of scalars, I'm not convinced that this is the API we should be building here. Instead I propose that we add the following lemmas:

section Semiring

variable {S : Type*} [Semiring S] [Module S M]

lemma sup_inf_assoc_of_le_of_neg_mem_iff
    {s p : Submodule S M} (t : Submodule S M) (hp : ∀ x, -x ∈ s ↔ x ∈ s) (hsp : s ≤ p) :
    (s ⊔ t) ⊓ p = s ⊔ (t ⊓ p) := by
  sorry

lemma inf_sup_assoc_of_le_of_neg_mem_iff
    {s p : Submodule S M} (t : Submodule S M) (hp : ∀ x, -x ∈ p ↔ x ∈ p) (hsp : p ≤ s) :
    (s ⊓ t) ⊔ p = s ⊓ (t ⊔ p) := by
  rw [sup_comm, inf_comm, ← sup_inf_assoc_of_le_of_neg_mem_iff t hp hsp, inf_comm, sup_comm]

end Semiring

exactly here and while we're at it use this to golf the proof of modularity just below as follows

- instance : IsModularLattice (Submodule R M) :=
-   ⟨fun y z xz a ha => by
-     rw [mem_inf, mem_sup] at ha
-     rcases ha with ⟨⟨b, hb, c, hc, rfl⟩, haz⟩
-     rw [mem_sup]
-     refine ⟨b, hb, c, mem_inf.2 ⟨hc, ?_⟩, rfl⟩
-     rw [← add_sub_cancel_right c b, add_comm]
-     apply z.sub_mem haz (xz hb)⟩
+ instance : IsModularLattice (Submodule R M) :=
+   ⟨fun y z xz a ha => by rwa [← sup_inf_assoc_of_le_of_neg_mem_iff y (by simp) xz]⟩

I claim that the two lemmas should be sufficient for your needs since the following is true by simp:

example (S : Type*) {R M : Type*} [Ring R] [AddCommGroup M] [Semiring S]
    [Module S M] [Module R M] [SMul S R] [IsScalarTower S R M] {x : M} {p : Submodule R M} :
    -x ∈ p.restrictScalars S ↔ x ∈ p.restrictScalars S := by
  simp

@martinwintermath
Copy link
Copy Markdown
Contributor Author

martinwintermath commented Apr 1, 2026

Alright, I went with your versions for general submodules. The short proof for inf_sup_assoc_of_le_of_neg_mem_iff did not work though since there was a problem with the statement of the other lemma.

I do however really hope for the specialized versions for cones since it is a common enough use case in our local repo (which is about cone theory, and will be PR-ed bit by bit). I added these lemmas.

@martinwintermath martinwintermath changed the title feat(Algebra/Module/Submodule): Submodules over a ring are modular elements in the lattice of submodules over a semiring feat(Algebra/Module/Submodule): Symmetric submodules are modular elements in the lattice of submodules over a semiring Apr 1, 2026
@ocfnash
Copy link
Copy Markdown
Contributor

ocfnash commented Apr 1, 2026

I do however really hope that we can have the specialized versions for cones since it is a common enough use case. I added these lemmas.

Yes, I agree the specialisations for cones deserve to exist.

@github-actions github-actions bot removed the awaiting-author A reviewer has asked the author a question or requested changes. label Apr 1, 2026
@ocfnash ocfnash added the awaiting-author A reviewer has asked the author a question or requested changes. label Apr 2, 2026
@martinwintermath
Copy link
Copy Markdown
Contributor Author

martinwintermath commented Apr 12, 2026

-awaiting-author

@ocfnash I don't understand why this label was added last week, I implemented all requests, no?

@github-actions github-actions bot removed the awaiting-author A reviewer has asked the author a question or requested changes. label Apr 12, 2026
This is a version of `sup_inf_assoc_of_le` for the not-necessarily-modular lattice
of submodules over a semiring. -/
lemma sup_inf_assoc_of_le_of_neg_mem_iff {s : Submodule R M} (t : Submodule R M)
{p : Submodule R M} (hp : ∀ x, -x ∈ p ↔ x ∈ p) (hsp : s ≤ p) :
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You can weaken the assumption here slightly:

Suggested change
{p : Submodule R M} (hp : ∀ x, -x ∈ p ↔ x ∈ p) (hsp : s ≤ p) :
{p : Submodule R M} (hp : ∀ x, -x ∈ s ↔ x ∈ s) (hsp : s ≤ p) :

Copy link
Copy Markdown
Contributor Author

@martinwintermath martinwintermath Apr 12, 2026

Choose a reason for hiding this comment

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

I don't think this is weaker: s being symmetric and p being symmetric are independent statements. I think this changes the statement in a way that we don't want (I suspect it makes it trivially equivalent to inf_sup_assoc_of_le_of_neg_mem_iff rather than dual to it). Am I missing something?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You're quite right!

(I guess the reason I had left that review pending was that I was still thinking about this, and I then yesterday I just mindlessly submitted.)

Looking now, I think the "right" suggestion is that we should prove:

lemma sup_inf_assoc_of_neg_le_of_le {s : Submodule R M} (t : Submodule R M)
    {p : Submodule R M} (hp : {-x | x ∈ s} ≤ p) (hsp : s ≤ p) :
    (s ⊔ t) ⊓ p = s ⊔ (t ⊓ p) := by

If we do this then we do get a symmetric lemma below as follows:

lemma inf_sup_assoc_of_neg_le_of_le {s : Submodule R M} (t : Submodule R M)
    {p : Submodule R M} (hp : {-x | x ∈ p} ≤ s) (hsp : p ≤ s) :
    (s ⊓ t) ⊔ p = s ⊓ (t ⊔ p) := by
  rw [sup_comm, inf_comm, ← sup_inf_assoc_of_le_of_neg_mem_iff t hp hsp, inf_comm, sup_comm]

and I note that these assumptions are true weakenings in view of:

example {s p : Submodule R M} (hp : ∀ x, -x ∈ p ↔ x ∈ p) (hsp : s ≤ p) :
    {-x | x ∈ s} ≤ p := by
  rintro - ⟨x, hx, rfl⟩
  aesop

example {s p : Submodule R M} (hp : ∀ x, -x ∈ p ↔ x ∈ p) (hsp : p ≤ s) :
    {-x | x ∈ p} ≤ s := by
  rintro - ⟨x, hx, rfl⟩
  aesop

Copy link
Copy Markdown
Contributor Author

@martinwintermath martinwintermath Apr 13, 2026

Choose a reason for hiding this comment

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

That works. The one thing that bothers me is that {-x | x ∈ s} ≤ p should be written as -s ≤ p but we can't access Submodule.instPointwiseNeg without creating circular imports. I would need to move to another file. But then I can't use it to prove IsModuleLattice for submodules.

I can write it as ∀ x ∈ s, -x ∈ p (and the previous versions should also have been written as ∀ x ∈ p, -x ∈ p since we need only one direction of the ).

Copy link
Copy Markdown
Contributor Author

@martinwintermath martinwintermath Apr 13, 2026

Choose a reason for hiding this comment

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

@ocfnash Okay I implemented it locally. I agree that your versions are more intellectually pleasing. But they are also a bit more cumbersome to use since the new hypothesis is not provable from only a simp anymore. Should we have both versions? What do you think?

Copy link
Copy Markdown
Contributor Author

@martinwintermath martinwintermath Apr 13, 2026

Choose a reason for hiding this comment

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

@ocfnash Regarding the Pointwise locale: I think we have an unfortunate import order. There are six lemmas in Pointwise.lean that mention the span; five of them cause problems when Span/Basic.lean is removed as an import. I think that these lemmas should be moved to Span/Basic.lean. Then the import order can be reversed, and we can write the hypothesis as -s ≤ p. This seems correct because other lemmas already make use of pointwise negation, e.g. -s when s : Set M.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm happy to prioritise getting this PR with your cone lemmas into master and leave a bit of clean up for a subsequent PR which either you or I could do.

I see the argument for reversing the import order (and I note your point about the shortcomings of the existing lemma span_neg) but I think sorting this all out might be a little annoying. If you really want to attempt this as part of these changes then that is great, but I don't think that has to happen.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I agree. I implemented your weakened hypotheses (and removed the other versions) and will approve the PR once CI went through. The rest is for a future PR.

Comment on lines +485 to +494
ext x
simp only [mem_inf, mem_sup]
constructor
· rintro ⟨y, ⟨hys, hyt⟩, z, hzp, hyzx⟩
exact ⟨by simpa [← hyzx] using add_mem hys (hsp hzp), ⟨y, hyt, z, hzp, hyzx⟩⟩
· rintro ⟨hxs, y, hyt, z, hzp, hyzx⟩
use y
refine ⟨⟨?_, hyt⟩, ⟨z, hzp, hyzx⟩⟩
rw [← add_left_inj, add_neg_cancel_right] at hyzx
simpa [hyzx] using add_mem hxs <| hsp <| (hp _).mpr hzp
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

With the suggestion above, this can be just:

Suggested change
ext x
simp only [mem_inf, mem_sup]
constructor
· rintro ⟨y, ⟨hys, hyt⟩, z, hzp, hyzx⟩
exact ⟨by simpa [← hyzx] using add_mem hys (hsp hzp), ⟨y, hyt, z, hzp, hyzx⟩⟩
· rintro ⟨hxs, y, hyt, z, hzp, hyzx⟩
use y
refine ⟨⟨?_, hyt⟩, ⟨z, hzp, hyzx⟩⟩
rw [← add_left_inj, add_neg_cancel_right] at hyzx
simpa [hyzx] using add_mem hxs <| hsp <| (hp _).mpr hzp
rw [sup_comm, inf_comm, ← sup_inf_assoc_of_le_of_neg_mem_iff t hp hsp, inf_comm, sup_comm]

@ocfnash
Copy link
Copy Markdown
Contributor

ocfnash commented Apr 12, 2026

I don't understand why this label was added last week, I implemented all requests, no?

Apologies @martinwintermath I had written two more suggestions but not clicked GitHub's "Submit review" button so they were visible to me (albeit with some "Pending" text which I failed to notice) but not to you.

Copy link
Copy Markdown
Contributor

@ocfnash ocfnash left a comment

Choose a reason for hiding this comment

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

Thanks!

I've left one last suggestion. I think it would be nice to take this up, but I won't insist.

bors d+

This is a version of `sup_inf_assoc_of_le` for the not-necessarily-modular lattice
of submodules over a semiring. -/
lemma sup_inf_assoc_of_le_of_neg_mem_iff {s : Submodule R M} (t : Submodule R M)
{p : Submodule R M} (hp : ∀ x, -x ∈ p ↔ x ∈ p) (hsp : s ≤ p) :
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You're quite right!

(I guess the reason I had left that review pending was that I was still thinking about this, and I then yesterday I just mindlessly submitted.)

Looking now, I think the "right" suggestion is that we should prove:

lemma sup_inf_assoc_of_neg_le_of_le {s : Submodule R M} (t : Submodule R M)
    {p : Submodule R M} (hp : {-x | x ∈ s} ≤ p) (hsp : s ≤ p) :
    (s ⊔ t) ⊓ p = s ⊔ (t ⊓ p) := by

If we do this then we do get a symmetric lemma below as follows:

lemma inf_sup_assoc_of_neg_le_of_le {s : Submodule R M} (t : Submodule R M)
    {p : Submodule R M} (hp : {-x | x ∈ p} ≤ s) (hsp : p ≤ s) :
    (s ⊓ t) ⊔ p = s ⊓ (t ⊔ p) := by
  rw [sup_comm, inf_comm, ← sup_inf_assoc_of_le_of_neg_mem_iff t hp hsp, inf_comm, sup_comm]

and I note that these assumptions are true weakenings in view of:

example {s p : Submodule R M} (hp : ∀ x, -x ∈ p ↔ x ∈ p) (hsp : s ≤ p) :
    {-x | x ∈ s} ≤ p := by
  rintro - ⟨x, hx, rfl⟩
  aesop

example {s p : Submodule R M} (hp : ∀ x, -x ∈ p ↔ x ∈ p) (hsp : p ≤ s) :
    {-x | x ∈ p} ≤ s := by
  rintro - ⟨x, hx, rfl⟩
  aesop

@mathlib-bors
Copy link
Copy Markdown
Contributor

mathlib-bors bot commented Apr 13, 2026

✌️ martinwintermath can now approve this pull request. To approve and merge a pull request, simply reply with bors r+. More detailed instructions are available here.

@mathlib-triage mathlib-triage bot added the delegated This pull request has been delegated to the PR author (or occasionally another non-maintainer). label Apr 13, 2026
@martinwintermath
Copy link
Copy Markdown
Contributor Author

bors r+

mathlib-bors bot pushed a commit that referenced this pull request Apr 13, 2026
…ents in the lattice of submodules over a semiring (#36689)

Add two lemmas that are replacements for modularity on the lattice of submodules that are not necessarily over a ring, but a semiring:

- `sup_inf_assoc_of_le_of_neg_le`: if `s ≤ p` and `-s ≤ p` then `(s ⊔ t) ⊓ p = s ⊔ (t ⊓ p)`
- `inf_sup_assoc_of_le_of_neg_le`: if `p ≤ s` and `-p ≤ s` then `(s ⊓ t) ⊔ p = s ⊓ (t ⊔ p)`

This allows to shorten the proof that the lattice of submodules over a ring is modular.

I also add specialized versions for cones.

Co-authored-by: Martin Winter <martin.winter.math@gmail.com>
@mathlib-bors
Copy link
Copy Markdown
Contributor

mathlib-bors bot commented Apr 13, 2026

Pull request successfully merged into master.

Build succeeded:

@mathlib-bors mathlib-bors bot changed the title feat(Algebra/Module/Submodule): Symmetric submodules are modular elements in the lattice of submodules over a semiring [Merged by Bors] - feat(Algebra/Module/Submodule): Symmetric submodules are modular elements in the lattice of submodules over a semiring Apr 13, 2026
@mathlib-bors mathlib-bors bot closed this Apr 13, 2026
@martinwintermath
Copy link
Copy Markdown
Contributor Author

Follow up PR: #38013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

delegated This pull request has been delegated to the PR author (or occasionally another non-maintainer). t-algebra Algebra (groups, rings, fields, etc)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants