Skip to content

Commit 5945e6f

Browse files
authored
Merge branch 'master' into feat/eigenvalues-lapMatrix-le-card
2 parents 024bc1e + b1007d8 commit 5945e6f

5 files changed

Lines changed: 296 additions & 2 deletions

File tree

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6705,6 +6705,7 @@ public import Mathlib.RingTheory.Coalgebra.Convolution
67056705
public import Mathlib.RingTheory.Coalgebra.Equiv
67066706
public import Mathlib.RingTheory.Coalgebra.GroupLike
67076707
public import Mathlib.RingTheory.Coalgebra.Hom
6708+
public import Mathlib.RingTheory.Coalgebra.IsFrobenius
67086709
public import Mathlib.RingTheory.Coalgebra.MonoidAlgebra
67096710
public import Mathlib.RingTheory.Coalgebra.MulOpposite
67106711
public import Mathlib.RingTheory.Coalgebra.Primitive
Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
/-
2+
Copyright (c) 2025 Monica Omar. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Monica Omar
5+
-/
6+
module
7+
8+
public import Mathlib.RingTheory.Bialgebra.Basic
9+
public import Mathlib.Algebra.Module.Projective
10+
public import Mathlib.LinearAlgebra.SesquilinearForm.Basic
11+
12+
import Mathlib.RingTheory.Coalgebra.CoassocSimps
13+
14+
/-!
15+
# Frobenius equations
16+
17+
This file defines `Coalgebra.IsFrobenius` and shows some elementary results.
18+
19+
A coalgebra with an algebra structure is said to be Frobenius when the Frobenius equation
20+
is satisfied:
21+
`(id ⊗ mul') ∘ assoc ∘ (comul ⊗ id) = (mul' ⊗ id) ∘ assoc.symm ∘ (id ⊗ comul)`,
22+
which in diagrams looks like
23+
```
24+
| | | |
25+
| μ μ |
26+
| / \ / \ |
27+
\ / | = | \ /
28+
δ | | δ
29+
| | | |
30+
```
31+
where `μ` stands for multiplication and `δ` for comultiplication.
32+
We define the left diagram as `Coalgebra.IsFrobenius.left` and the right as
33+
`Coalgebra.IsFrobenius.right` in order to shorten the names.
34+
35+
When the Frobenius equations are satisfied, we actually get
36+
`(id ⊗ mul') ∘ assoc ∘ (comul ⊗ id) = comul ∘ mul' = (mul' ⊗ id) ∘ assoc.symm ∘ (id ⊗ comul)`,
37+
which in diagrams looks like
38+
```
39+
| | | |
40+
| μ | | μ |
41+
| / \ \ / / \ |
42+
\ / | = δ ∘ μ = | \ /
43+
δ | / \ | δ
44+
| | | | | |
45+
```
46+
In texts, this is what the Frobenius equations are usually referred to as.
47+
48+
## Main definitions and results
49+
50+
* `Coalgebra.IsFrobenius`: the class for when a coalgebra satisfies the Frobenius equations
51+
* `Coalgebra.IsFrobenius.left_eq_comul_comp_mul'`:
52+
the left Frobenius equation `(id ⊗ mul') ∘ assoc ∘ (comul ⊗ id) = comul ∘ mul'`
53+
* `Coalgebra.IsFrobenius.right_eq_comul_comp_mul'`:
54+
the right Frobenius equation `(mul' ⊗ id) ∘ assoc.symm ∘ (id ⊗ comul) = comul ∘ mul'`
55+
* `Coalgebra.IsFrobenius.instFinite`: a coalgebra satisfying the Frobenius equations is finite
56+
* `Coalgebra.IsFrobenius.instProjective`: a coalgebra satisfying the Frobenius equations is
57+
projective
58+
* `Bialgebra.nonempty_algEquiv_of_isFrobenius`: when an `R`-bialgebra `A` satisfies the Frobenius
59+
equations, `R` is isomorphic to `A`
60+
61+
## TODO
62+
63+
* show `IsFrobenius R (A ⊗ B)`
64+
* show `IsFrobenius R (A × B)`
65+
66+
-/
67+
68+
public section
69+
70+
open TensorProduct LinearMap Coalgebra
71+
open scoped RingTheory.LinearMap
72+
73+
variable {R A : Type*} [CommSemiring R] [NonUnitalNonAssocSemiring A] [Module R A]
74+
[SMulCommClass R A A] [IsScalarTower R A A]
75+
76+
local notation3 "α" => (TensorProduct.assoc R _ _ _).toLinearMap
77+
local notation3 "α⁻¹" => (TensorProduct.assoc R _ _ _).symm.toLinearMap
78+
local notation3 "β" => (TensorProduct.lid R _).toLinearMap
79+
local notation3 "β⁻¹" => (TensorProduct.lid R _).symm.toLinearMap
80+
local notation "rT" => rTensor
81+
local notation "lT" => lTensor
82+
83+
/-! ### Definition and basic properties -/
84+
85+
section Defs
86+
variable (R A)
87+
variable [CoalgebraStruct R A]
88+
89+
/-- The left-hand side of the Frobenius equation: `(id ⊗ mul) ∘ assoc ∘ (comul ⊗ id)`. -/
90+
@[expose] def Coalgebra.IsFrobenius.left : A ⊗[R] A →ₗ[R] A ⊗[R] A := lT A μ[R] ∘ₗ α ∘ₗ rT A δ
91+
92+
lemma Coalgebra.IsFrobenius.left_def : left R A = lT A μ[R] ∘ₗ α ∘ₗ rT A δ := rfl
93+
94+
/-- The right-hand side of the Frobenius equation: `(mul ⊗ id) ∘ assoc.symm ∘ (id ⊗ comul)`. -/
95+
@[expose] def Coalgebra.IsFrobenius.right : A ⊗[R] A →ₗ[R] A ⊗[R] A := rT A μ[R] ∘ₗ α⁻¹ ∘ₗ lT A δ
96+
97+
lemma Coalgebra.IsFrobenius.right_def : right R A = rT A μ[R] ∘ₗ α⁻¹ ∘ₗ lT A δ := rfl
98+
99+
/-- A coalgebra with an algebra structure is said to be **Frobenius** when
100+
the Frobenius equation is satisfied, i.e., `IsFrobenius.left` and `IsFrobenius.right` are equal,
101+
in other words,
102+
103+
`(id ⊗ mul') ∘ assoc ∘ (comul ⊗ id) = (mul' ⊗ id) ∘ assoc.symm ∘ (id ⊗ comul)`.
104+
105+
See `IsFrobenius.left_eq` and `IsFrobenius.right_eq` which refer to each side of the equality
106+
being equal to `comul ∘ mul'`.
107+
108+
When the Frobenius equations are satisfied, the bilinear form `mul.compr₂ counit` is
109+
nondegenerate and bijective (see `IsFrobenius.nondegenerate_compr₂_mul_counit` and
110+
`IsFrobenius.bijective_compr₂_mul_counit`). -/
111+
class Coalgebra.IsFrobenius : Prop where
112+
/-- The Frobenius equation. -/
113+
left_eq_right : IsFrobenius.left R A = IsFrobenius.right R A
114+
115+
end Defs
116+
117+
namespace Coalgebra.IsFrobenius
118+
variable [Coalgebra R A] [IsFrobenius R A]
119+
120+
instance of_commSemiring : IsFrobenius R R where
121+
left_eq_right := by ext; simp [left_def, right_def]
122+
123+
lemma left_eq_comul_comp_mul' : left R A = δ ∘ₗ μ[R] := by
124+
have h := ‹IsFrobenius R A›.left_eq_right
125+
simp only [left_def, lTensor, rTensor, right_def] at h ⊢
126+
calc
127+
_ = rT A μ ∘ₗ α⁻¹ ∘ₗ ((β ∘ₗ rT A ε ∘ₗ δ) ⊗ₘ δ) := by
128+
simp [h, CoassocSimps.map_counit_comp_comul_left, coassoc_simps]
129+
_ = β ∘ₗ rT (A ⊗[R] A) ε ∘ₗ α ∘ₗ rT A (rT A μ ∘ₗ α⁻¹ ∘ₗ lT A δ) ∘ₗ α⁻¹ ∘ₗ lT A δ := by
130+
simp only [rTensor, lTensor, ← h, lid_tensor]
131+
simp [coassoc_simps, mul'_comp_map_lid_comp]
132+
_ = β ∘ₗ (ε ⊗ₘ δ) ∘ₗ lT A μ ∘ₗ α ∘ₗ rT A δ := by simp [assoc_tensor, h, coassoc_simps]
133+
_ = β ∘ₗ lT R (δ ∘ₗ μ) ∘ₗ α ∘ₗ rT A (rT A ε ∘ₗ δ) := by simp [coassoc_simps]
134+
_ = δ ∘ₗ μ := by simp [coassoc_simps, CoassocSimps.map_counit_comp_comul_left]
135+
136+
lemma right_eq_comul_comp_mul' : right R A = δ ∘ₗ μ[R] := by
137+
rw [← left_eq_right, left_eq_comul_comp_mul']
138+
139+
/-! ### Unital coalgebras
140+
141+
When our coalgebra is unital and satisfies the Frobenius equations, we get that the counit is
142+
nondegenerate, and that it is finite and projective. -/
143+
144+
section nonAssoc
145+
variable {A : Type*} [NonAssocSemiring A] [Module R A] [Coalgebra R A]
146+
[SMulCommClass R A A] [IsScalarTower R A A] [IsFrobenius R A]
147+
148+
private lemma sum_counit_mul_left_smul_of_comul_one {S : Finset (A × A)}
149+
(hS : δ (1 : A) = ∑ i ∈ S, i.1 ⊗ₜ[R] i.2) (a : A) :
150+
∑ x ∈ S, (ε : _ →ₗ[R] _) (a * x.1) • x.2 = a := by
151+
simpa [hS, tmul_sum, right_def] using congr(β (rT A ε ($right_eq_comul_comp_mul' (a ⊗ₜ[R] 1))))
152+
153+
private lemma sum_counit_mul_right_smul_of_comul_one {S : Finset (A × A)}
154+
(hS : δ (1 : A) = ∑ i ∈ S, i.1 ⊗ₜ[R] i.2) (a : A) :
155+
∑ x ∈ S, (ε : _ →ₗ[R] _) (x.2 * a) • x.1 = a := by
156+
simpa [hS, sum_tmul, left_def] using
157+
congr(TensorProduct.rid R A (lT A ε ($left_eq_comul_comp_mul' (1 ⊗ₜ[R] a))))
158+
159+
instance instFinite : Module.Finite R A := by
160+
have ⟨S, hS⟩ := exists_finset (R := R) (δ (1 : A))
161+
classical refine Module.finite_def.mpr ⟨S.image Prod.snd, top_le_iff.mp fun a _ ↦ ?_⟩
162+
rw [← sum_counit_mul_left_smul_of_comul_one hS a]
163+
exact sum_mem fun _ _ ↦ Submodule.smul_mem _ _ (Submodule.subset_span (by grind))
164+
165+
instance instProjective : Module.Projective R A := by
166+
have ⟨S, hS⟩ := exists_finset (R := R) (δ (1 : A))
167+
refine Module.projective_def'.mpr ⟨∑ p ∈ S, (ε ∘ₗ mulRight R p.1).smulRight (.single p.2 1), ?_⟩
168+
ext; simp [sum_counit_mul_left_smul_of_comul_one hS]
169+
170+
/-- The bilinear form `(mul R A).compr₂ counit` is separating left.
171+
This is the simplified version, see `nondegenerate_compr₂_mul_counit`. -/
172+
lemma forall_counit_mul_left_eq_zero_iff {a : A} : (∀ b, (ε : _ →ₗ[R] _) (a * b) = 0) ↔ a = 0 := by
173+
refine ⟨fun h ↦ ?_, fun h _ ↦ by simp [h]⟩
174+
have ⟨S, hS⟩ := exists_finset (R := R) (δ (1 : A))
175+
simpa [h] using (sum_counit_mul_left_smul_of_comul_one hS a).symm
176+
177+
/-- The bilinear form `(mul R A).compr₂ counit` is separating right.
178+
This is the simplified version, see `nondegenerate_compr₂_mul_counit`. -/
179+
lemma forall_counit_mul_right_eq_zero_iff {a : A} : (∀ b, (ε : _ →ₗ[R] _) (b * a) = 0) ↔ a = 0 := by
180+
refine ⟨fun h ↦ ?_, fun h _ ↦ by simp [h]⟩
181+
have ⟨S, hS⟩ := exists_finset (R := R) (δ (1 : A))
182+
simpa [hS, sum_tmul, h] using (sum_counit_mul_right_smul_of_comul_one hS a).symm
183+
184+
/-- The bilinear form `mul.compr₂ counit` is nondegenerate. -/
185+
lemma nondegenerate_compr₂_mul_counit : ((mul R A).compr₂ ε).Nondegenerate :=
186+
fun _ ↦ forall_counit_mul_left_eq_zero_iff.mp, fun _ ↦ forall_counit_mul_right_eq_zero_iff.mp⟩
187+
188+
/-- The bilinear form `mul.compr₂ counit` is bijective. -/
189+
lemma compr₂_mul_counit_bijective : (⇑((mul R A).compr₂ ε)).Bijective := by
190+
have ⟨S, hS⟩ := exists_finset (R := R) (δ (1 : A))
191+
refine ⟨fun a b h ↦ ?_, fun f ↦ ⟨∑ x ∈ S, f x.1 • x.2, ext fun b ↦ ?_⟩⟩
192+
· rw [← sum_counit_mul_left_smul_of_comul_one hS b]
193+
simp only [LinearMap.ext_iff, compr₂_apply, mul_apply_apply] at h
194+
simp [← h, sum_counit_mul_left_smul_of_comul_one hS]
195+
· calc _ = ∑ x ∈ S, (ε (x.2 * b) : R) • f x.1 := by simp [mul_comm (f _)]
196+
_ = _ := by simp only [← map_smul, ← map_sum, sum_counit_mul_right_smul_of_comul_one hS]
197+
198+
end nonAssoc
199+
200+
/-! ### The snake equations
201+
202+
Composing the Frobenius equations with the counit and algebra map gives the so called "snake"
203+
equations. -/
204+
205+
section Algebra
206+
variable {A : Type*} [Semiring A] [Algebra R A] [Coalgebra R A] [IsFrobenius R A]
207+
208+
/-- Composing the left Frobenius equation with `Coalgebra.counit` and `Algebra.linearMap`.
209+
See `rTensor_counit_comp_right_comp_lTensor_algebraLinearMap` for the right Frobenius equation
210+
version.
211+
212+
(This is sometimes known as the left snake equation.) -/
213+
lemma lTensor_counit_comp_left_comp_rTensor_algebraLinearMap :
214+
lT A ε ∘ₗ left R A ∘ₗ rT A η[R] = (TensorProduct.comm R R A).toLinearMap := by
215+
ext; simp [left_eq_comul_comp_mul']
216+
217+
/-- Composing the right Frobenius equation with `Coalgebra.counit` and `Algebra.linearMap`.
218+
See `lTensor_counit_comp_left_comp_rTensor_algebraLinearMap` for the left Frobenius equation
219+
version.
220+
221+
(This is sometimes known as the right snake equation.) -/
222+
lemma rTensor_counit_comp_right_comp_lTensor_algebraLinearMap :
223+
rT A ε ∘ₗ right R A ∘ₗ lT A η[R] = (TensorProduct.comm R A R).toLinearMap := by
224+
ext; simp [right_eq_comul_comp_mul']
225+
226+
end Algebra
227+
228+
end Coalgebra.IsFrobenius
229+
230+
/-! ### Bialgebras and the Frobenius equations
231+
232+
If a bialgebra `A` over `R` satisfies the Frobenius equations, then `A` is
233+
isomorphic to the underlying ring `R`. -/
234+
235+
namespace Bialgebra
236+
variable {A : Type*} [Semiring A] [Bialgebra R A] [IsFrobenius R A]
237+
238+
@[simp] lemma comul_apply_eq_of_isFrobenius (a : A) : δ a = a ⊗ₜ[R] 1 := by
239+
simpa [Algebra.TensorProduct.one_def, IsFrobenius.right_def] using
240+
congr($IsFrobenius.right_eq_comul_comp_mul' (a ⊗ₜ[R] 1)).symm
241+
242+
lemma comul_eq_of_isFrobenius : δ = (TensorProduct.mk R A A).flip 1 :=
243+
ext comul_apply_eq_of_isFrobenius
244+
245+
@[simp] lemma algebraMap_counit_of_isFrobenius (a : A) : algebraMap R A (ε a) = a := by
246+
simpa [Algebra.algebraMap_eq_smul_one] using congr(β ($rTensor_counit_comp_comul a))
247+
248+
lemma algebraMap_bijective_of_isFrobenius : Function.Bijective (algebraMap R A) :=
249+
⟨algebraMap_injective A, fun a ↦ ⟨ε a, by simp⟩⟩
250+
251+
lemma counit_bijective_of_isFrobenius : Function.Bijective (ε : A →ₗ[R] R) :=
252+
⟨Function.LeftInverse.injective algebraMap_counit_of_isFrobenius, counit_surjective⟩
253+
254+
/-- When a bialgebra satisfies the Frobenius equations, we get `R ≃ A`.
255+
So if `R` and `A` are not isomorphic, then `A` cannot satisfy the Frobenius equations. -/
256+
lemma algebraOfId_bijective_of_isFrobenius : Function.Bijective (Algebra.ofId R A) :=
257+
algebraMap_bijective_of_isFrobenius
258+
259+
end Bialgebra

Mathlib/RingTheory/TensorProduct/Basic.lean

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,17 @@ instance (priority := 100) sMulCommClass_right [Monoid S] [DistribMulAction S A]
198198
| add x y hx hy => simp [smul_add, add_mul _, *]
199199
| add x y hx hy => simp [smul_add, mul_add _, *]
200200

201+
open scoped RingTheory.LinearMap in
202+
lemma _root_.LinearMap.mul'_comp_map_lid_comp {M N : Type*} [AddCommMonoid M] [Module R M]
203+
[AddCommMonoid N] [Module R N] (f : M →ₗ[R] R ⊗[R] A) (g : N →ₗ[R] A) :
204+
μ[R] ∘ₗ ((TensorProduct.lid R A ∘ₗ f) ⊗ₘ g) =
205+
TensorProduct.lid R A ∘ₗ LinearMap.lTensor R μ ∘ₗ
206+
(TensorProduct.assoc R R A A).toLinearMap ∘ₗ (f ⊗ₘ g) := by
207+
trans μ[R] ∘ₗ (LinearMap.rTensor A (TensorProduct.lid R A)) ∘ₗ (f ⊗ₘ g)
208+
· ext; simp
209+
simp only [← LinearMap.comp_assoc]
210+
congr 1; ext; simp
211+
201212
end NonUnitalNonAssocSemiring
202213

203214
section NonAssocSemiring

Mathlib/Tactic/Inclusion/Core/DiscrTreeExt.lean

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,19 @@ variable {α : Type}
5959
/-- Return the declaration values whose `DiscrTree` keys match `e`. -/
6060
def State.getMatch (state : State α) (e : Expr) : MetaM (Array α) := state.tree.getMatch e
6161

62+
/-- When the current module registers an attribute, record for `shake` that modules importing
63+
the current one should continue to do so.
64+
65+
`kind` indicates the scope at which the attribute is registered.
66+
67+
TODO: This is an overly conservative approximation: better would be to record at the use site
68+
which tagged declarations are actually used.
69+
-/
70+
def recordRegisteringModule (kind : AttributeKind) : CoreM Unit := do
71+
-- A `local` registration does not outlive the current file, so nothing downstream can need it.
72+
unless kind == .local do
73+
recordExtraRevUseOfCurrentModule
74+
6275
/-- Create a scoped environment extension whose declarations have type `typeName`. By default, the
6376
environment extension is named after the declaration in which this function is called. -/
6477
def initializeEnvExt (typeName : Name)
@@ -75,6 +88,15 @@ def initializeEnvExt (typeName : Name)
7588
{ tree := insert kss ext state.tree }
7689
}
7790

91+
/-- Register `entry` in `ext`, recording the current module as one `shake` should preserve.
92+
93+
Prefer this over `ScopedEnvExtension.add` when adding an entry from an attribute handler, so that
94+
the registration and the `shake` bookkeeping cannot drift apart. -/
95+
def EnvExt.register (ext : EnvExt α) (entry : Entry × α) (kind : AttributeKind) :
96+
CoreM Unit := do
97+
ext.add entry kind
98+
recordRegisteringModule kind
99+
78100
/-- Elaborate expression patterns into `DiscrTree` paths. -/
79101
def elabExtKeys (patterns : Array Syntax) : CoreM (Array (Array DiscrTree.Key)) :=
80102
MetaM.run' <| patterns.mapM fun stx => do

Mathlib/Tactic/Inclusion/ExtensionAPI/Attr.lean

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ def addInclusionParam (declName : Name) (kind : AttributeKind) : AttrM Unit := d
4444
if params.contains decl.name then
4545
throwError "Inclusion parameter `{decl.name}` is already registered"
4646
inclusionParamExt.add (declName, decl) kind
47+
recordRegisteringModule kind
4748

4849
initialize registerBuiltinAttribute {
4950
name := `inclusionParamAttr
@@ -60,7 +61,7 @@ def addInclusionExt (declName : Name) (keys : Array (Array DiscrTree.Key))
6061
(kind : AttributeKind) : AttrM Unit := do
6162
let ext ← evalDecl InclusionExt ``InclusionExt declName
6263
let family ← getInclusionFamily ext.family
63-
family.inclusionExt.add ((keys, declName), ext) kind
64+
family.inclusionExt.register ((keys, declName), ext) kind
6465

6566
initialize registerBuiltinAttribute {
6667
name := `inclusionExtAttr
@@ -87,7 +88,7 @@ def addHypothesisExt (declName : Name) (keys : Array (Array DiscrTree.Key))
8788
(kind : AttributeKind) : AttrM Unit := do
8889
let ext ← evalDecl HypothesisExt ``HypothesisExt declName
8990
let family ← getInclusionFamily ext.family
90-
family.hypothesisExt.add ((keys, declName), ext) kind
91+
family.hypothesisExt.register ((keys, declName), ext) kind
9192

9293
/-- Register the `hypothesis_ext` attribute. -/
9394
initialize registerBuiltinAttribute {

0 commit comments

Comments
 (0)