Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

feat(linear_algebra/decomposition): Define module decompositions and prove basic facts#8246

Open
winston-h-zhang wants to merge 42 commits intomasterfrom
module-decompositions
Open

feat(linear_algebra/decomposition): Define module decompositions and prove basic facts#8246
winston-h-zhang wants to merge 42 commits intomasterfrom
module-decompositions

Conversation

@winston-h-zhang
Copy link
Copy Markdown
Collaborator

@winston-h-zhang winston-h-zhang commented Jul 10, 2021

We define a new structure decomposition ι R M as the type of ι-indexed decompositions of M. We provide a correspondence between internal direct sums and decompositions. Some helpful auxiliary lemmas have been added as well.


Suggestions or criticisms about how I could do this better is certainly welcome!

Open in Gitpod


open_locale direct_sum classical big_operators
open classical linear_map dfinsupp direct_sum
noncomputable theory
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'd be interested to know exactly which bits of this are noncomputable.

My hunch right now is that this is not a good choice of definition of decomposition; I think the decomposition should just hold the actual equiv, and you should have a noncomputablr def decomposition.of_independent that constructs one from the fields you currently have.

Copy link
Copy Markdown
Collaborator Author

@winston-h-zhang winston-h-zhang Jul 10, 2021

Choose a reason for hiding this comment

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

Are there code/formalization specific benefits to holding to actual equiv? I'm not attached to my definition; they all look equivalent to me.

def decomposition (ι : Type u) (R : Type v) (M : Type w)
  [semiring R] [add_comm_monoid M] [module R M] := 
subtype (λ (p : ι → submodule R M), submodule_is_internal p)


structure decomposition' (ι : Type u) (R : Type v) (M : Type w)
  [semiring R] [add_comm_monoid M] [module R M] := 
(factors : ι → submodule R M)
(to_equiv : (⨁ i, factors i) ≃ₗ[R] M)

These were the two other definitions I was thinking about, but they honestly look exactly the same :P

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

To be clear by "hold the actual equiv" I assume you mean something like the second one?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes, although I guess you don't want to hold the equiv, rather just the inverse and the proof it is an inverse of the function we care about.

The advantage of doing that is you can compute with decompositions.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I can reply with a mwe on Monday, but can't really do so from mobile.

Copy link
Copy Markdown
Member

@eric-wieser eric-wieser left a comment

Choose a reason for hiding this comment

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

Thanks for taking this on! 🎉

@eric-wieser eric-wieser added the awaiting-author A reviewer has asked the author a question or requested changes label Jul 10, 2021
@github-actions github-actions bot added the merge-conflict Please `git merge origin/master` then a bot will remove this label. label Jul 10, 2021
Comment on lines +1233 to +1327
-- pretty atrocious but hey it works
lemma mem_supr'
{ι : Type w} (p : ι → submodule R M) {x : M} :
x ∈ supr p ↔ ∃ v : ι →₀ M, (∀ i, v i ∈ p i) ∧ ∑ i in v.support, v i = x :=
begin
classical,
rw submodule.supr_eq_span,
refine ⟨λ h, _, λ h, _⟩,
refine submodule.span_induction h _ _ _ _,
{ intros y hy,
rw set.mem_Union at hy,
cases hy with i hy,
use finsupp.single i y,
split,
{ intro j, by_cases h : j = i,
simp only [h, finsupp.single_eq_same], exact hy,
rw ← ne.def at h,
simp only [finsupp.single_eq_of_ne h.symm, submodule.zero_mem], },
by_cases hy : y = 0, rw hy,
simp only [finsupp.coe_zero, pi.zero_apply, finsupp.single_zero, finset.sum_const_zero],
rw [finsupp.support_single_ne_zero hy, finset.sum_singleton],
exact finsupp.single_eq_same, },
{ use 0,
simp only [finsupp.coe_zero, pi.zero_apply, implies_true_iff, eq_self_iff_true, and_self,
finset.sum_const_zero, submodule.zero_mem], },
{ intros x y hx hy,
rcases hx with ⟨v, hv, hvs⟩,
rcases hy with ⟨w, hw, hws⟩,
use v + w,
refine ⟨λ i, submodule.add_mem _ (hv i) (hw i), _⟩,
rw [← hvs, ← hws],
simp only [finsupp.add_apply],
convert finsupp.sum_add_add v w, },
{ intros r x hx,
rcases hx with ⟨v, hv, hvs⟩,
use r • v,
refine ⟨λ i, submodule.smul_mem _ _ (hv i), _⟩,
rw [← hvs, finset.smul_sum],
simp only [finsupp.smul_apply],
refine finset.sum_subset finsupp.support_smul
(λ a ha han, finsupp.not_mem_support_iff.mp han) },
rcases h with ⟨v, hv, hvs⟩,
have := submodule.sum_mem (supr p) (λ i _, (le_supr p i : p i ≤ supr p) (hv i)),
rw ← submodule.supr_eq_span,
rwa hvs at this,
end

-- this is **definitely** going to be atrocious
lemma mem_bsupr {p : ι → Prop} (f : ι → submodule R M) (x : M) :
x ∈ (⨆ i (H : p i), f i) ↔
∃ v : ι →₀ M, (∀ i, v i ∈ f i) ∧ ∑ i in v.support, v i = x ∧ (∀ i, ¬ p i → v i = 0) :=
begin
classical,
change set ι at p,
refine ⟨λ h, _, λ h, _⟩,
{ rw bsupr_eq_supr at h,
rcases (mem_supr' _).mp h with ⟨v', hv', hsum⟩,
change p →₀ M at v',
-- define `v = v'` where `p i` is true and zero otherwise
let v : ι →₀ M :=
⟨v'.support.map (function.embedding.subtype p),
λ (i : ι), dite (p i) (λ hi, v' ⟨i, hi⟩) (λ _, 0), _⟩,
refine ⟨v, _, _, _⟩,
{ intros i,
simp only [finsupp.coe_mk],
split_ifs with hi,
{ exact hv' ⟨i, hi⟩ },
exact zero_mem _ },
{ simp only [finsupp.coe_mk, dite_eq_ite, function.embedding.coe_subtype, finset.sum_map,
subtype.coe_eta],
convert hsum,
ext i, split_ifs with hi, refl,
exfalso, apply hi, exact i.2 },
{ intros i hi,
simp only [finsupp.coe_mk, dif_neg hi], },
intros i,
simp only [exists_prop, function.embedding.coe_subtype, set_coe.exists, finset.mem_map,
exists_and_distrib_right, exists_eq_right, finsupp.mem_support_iff, ne.def, subtype.coe_mk],
split_ifs with hi,
{ refine ⟨λ hh, _, λ hh, ⟨hi, hh⟩⟩,
cases hh with _ key, exact key },
refine ⟨λ hh _, _, λ hh, _⟩,
{ cases hh with key _,
exact hi key },
exfalso, exact hh rfl },
rcases h with ⟨v, hv, hsum, hzero⟩,
have hle: (⨆ i ∈ v.support, f i) ≤ ⨆ (i : ι) (H : p i), f i,
{ refine bsupr_le_bsupr' (λ i hi, _),
revert hi, contrapose!,
refine λ h, finsupp.not_mem_support_iff.mpr (hzero i h), },
have key: x ∈ ⨆ i ∈ v.support, f i,
{ rw ← hsum, exact sum_mem_bsupr (λ i hi, hv i), },
exact hle key,
end

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think it might be worth splitting these two proofs (and anything you added in order to prove them) into their own smaller PR, and asking zulip for help golfing them. This PR is great, but it's also large, and if you split it up you can get more focussed feedback on each part.

…ubmodule}.[d]finsupp_sum_mem`

These lemmas are trivial consequences of the finset lemmas, but having them avoids having to unfold `[d]finsupp.sum`.

`dfinsupp_sum_add_hom_mem` is particularly useful because this one has some messy decidability arguments to eliminate.
Comment on lines +1413 to +1416
-- this is **definitely** going to be atrocious
lemma mem_bsupr {p : ι → Prop} (f : ι → submodule R M) (x : M) :
x ∈ (⨆ i (H : p i), f i) ↔
∃ v : ι →₀ M, (∀ i, v i ∈ f i) ∧ ∑ i in v.support, v i = x ∧ (∀ i, ¬ p i → v i = 0) :=
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I've PR'd an alternate version of this as #9202

bors bot pushed a commit that referenced this pull request Sep 24, 2021
Also a version for `add_submonoid`. Unfortunately the proofs are almost identical, but that's consistent with the surrounding bits of the file anyway.

The key result is a dfinsupp version of the lemma in #8246,
```lean
x ∈ (⨆ i (H : p i), f i) ↔ ∃ v : ι →₀ M, (∀ i, v i ∈ f i) ∧ ∑ i in v.support, v i = x ∧ (∀ i, ¬ p i → v i = 0) :=
```
as
```lean
x ∈ (⨆ i (h : p i), S i) ↔ ∃ f : Π₀ i, S i, dfinsupp.lsum ℕ (λ i, (S i).subtype) (f.filter p) = x
```
bors bot pushed a commit that referenced this pull request Sep 24, 2021
Also a version for `add_submonoid`. Unfortunately the proofs are almost identical, but that's consistent with the surrounding bits of the file anyway.

The key result is a dfinsupp version of the lemma in #8246,
```lean
x ∈ (⨆ i (H : p i), f i) ↔ ∃ v : ι →₀ M, (∀ i, v i ∈ f i) ∧ ∑ i in v.support, v i = x ∧ (∀ i, ¬ p i → v i = 0) :=
```
as
```lean
x ∈ (⨆ i (h : p i), S i) ↔ ∃ f : Π₀ i, S i, dfinsupp.lsum ℕ (λ i, (S i).subtype) (f.filter p) = x
```
bors bot pushed a commit that referenced this pull request Oct 1, 2021
…nt_and_supr_eq_top` (#9214)

This shows that a grade decomposition into submodules is bijective iff and only iff the submodules are independent and span the whole module.

The key proofs are:
* `complete_lattice.independent_of_dfinsupp_lsum_injective`
* `complete_lattice.independent.dfinsupp_lsum_injective`

Everything else is just glue.

This replaces parts of #8246, and uses what is probably a similar proof strategy, but without unfolding down to finsets.

Unlike the proof there, this requires only `add_comm_monoid` for the `complete_lattice.independent_of_dfinsupp_lsum_injective` direction of the proof. I was not able to find a proof of `complete_lattice.independent.dfinsupp_lsum_injective` with the same weak assumptions, as it is not true! A counter-example is included,

Co-authored-by: Hanting Zhang <hantingzhang03@gmail.com>
@github-actions github-actions bot added the merge-conflict Please `git merge origin/master` then a bot will remove this label. label Oct 1, 2021
@eric-wieser
Copy link
Copy Markdown
Member

@acxxa, I think #9202 contains most of the interesting proofs from this PR; all that's left is the decomposition API.

Did you have a motivation for bundling factors rather than leaving it unbundled? Was there something you planned to build on top of this?

This removes some proofs which now already exist more generally
@github-actions github-actions bot removed the merge-conflict Please `git merge origin/master` then a bot will remove this label. label Oct 4, 2021
@eric-wieser eric-wieser force-pushed the module-decompositions branch from 881acb5 to 5ea4fe8 Compare October 4, 2021 13:20
@github-actions github-actions bot added the blocked-by-other-PR This PR depends on another PR which is still in the queue. A bot manages this label via PR comment. label Oct 20, 2021
which phased out of the `set` design because of problems with it.
-/
@[nolint has_inhabited_instance]
structure decomposition (ι : Type u) (R : Type v) (M : Type w)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This bears a resemblance to #10115. Both approaches have their merits, but I hope we can get the best of both.

@eric-wieser
Copy link
Copy Markdown
Member

Note that graded_algebra is now merged. I think probably to make it play well with this PR, we want to change it's definition from

class graded_algebra extends set_like.graded_monoid 𝒜 :=
(decompose' : A → ⨁ i, 𝒜 i)
(left_inv : function.left_inverse decompose' (direct_sum.submodule_coe 𝒜))
(right_inv : function.right_inverse decompose' (direct_sum.submodule_coe 𝒜))

to

-- this is essentially your `decomposition`
class graded_module :=
(decompose' : A → ⨁ i, 𝒜 i)
(left_inv : function.left_inverse decompose' (direct_sum.submodule_coe 𝒜))
(right_inv : function.right_inverse decompose' (direct_sum.submodule_coe 𝒜))

class graded_algebra extends set_like.graded_monoid 𝒜, graded_module 𝒜

@leanprover-community-bot-assistant leanprover-community-bot-assistant added the merge-conflict Please `git merge origin/master` then a bot will remove this label. label Mar 15, 2022
@ghost ghost removed the blocked-by-other-PR This PR depends on another PR which is still in the queue. A bot manages this label via PR comment. label Apr 21, 2023
@ghost ghost deleted a comment from github-actions bot Apr 21, 2023
@github-actions github-actions bot added the modifies-synchronized-file This PR touches a files that has already been ported to mathlib4, and may need a synchronization PR. label Apr 22, 2023
@YaelDillies YaelDillies added RFC Request for comment and removed awaiting-author A reviewer has asked the author a question or requested changes merge-conflict Please `git merge origin/master` then a bot will remove this label. labels Apr 22, 2023
@YaelDillies
Copy link
Copy Markdown
Collaborator

@eric-wieser, what's your opinion on this PR nowadays?

@YaelDillies YaelDillies added the t-algebra Algebra (groups, rings, fields etc) label May 9, 2023
@kim-em kim-em added the too-late This PR was ready too late for inclusion in mathlib3 label Jul 16, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

modifies-synchronized-file This PR touches a files that has already been ported to mathlib4, and may need a synchronization PR. RFC Request for comment t-algebra Algebra (groups, rings, fields etc) too-late This PR was ready too late for inclusion in mathlib3

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants