Skip to content

Commit

Permalink
feat(group_theory/group_action/sub_mul_action): Add an object for bun…
Browse files Browse the repository at this point in the history
…dled sets closed under a mul action (#4996)

This adds `sub_mul_action` as a base class for `submodule`, and copies across the relevant lemmas.

This also weakens the type class requires for `A →[R] B`, to allow it to be used when only `has_scalar` is available.
  • Loading branch information
eric-wieser committed Dec 3, 2020
1 parent 98a20c2 commit f6273d4
Show file tree
Hide file tree
Showing 3 changed files with 190 additions and 23 deletions.
35 changes: 18 additions & 17 deletions src/algebra/group_action_hom.lean
Expand Up @@ -26,10 +26,11 @@ import group_theory.group_action
-/

variables (M' : Type*)
variables (X : Type*) [has_scalar M' X]
variables (Y : Type*) [has_scalar M' Y]
variables (Z : Type*) [has_scalar M' Z]
variables (M : Type*) [monoid M]
variables (X : Type*) [mul_action M X]
variables (Y : Type*) [mul_action M Y]
variables (Z : Type*) [mul_action M Z]
variables (A : Type*) [add_monoid A] [distrib_mul_action M A]
variables (A' : Type*) [add_group A'] [distrib_mul_action M A']
variables (B : Type*) [add_monoid B] [distrib_mul_action M B]
Expand All @@ -48,48 +49,48 @@ set_option old_structure_cmd true
@[nolint has_inhabited_instance]
structure mul_action_hom :=
(to_fun : X → Y)
(map_smul' : ∀ (m : M) (x : X), to_fun (m • x) = m • to_fun x)
(map_smul' : ∀ (m : M') (x : X), to_fun (m • x) = m • to_fun x)

notation X ` →[`:25 M:25 `] `:0 Y:0 := mul_action_hom M X Y

namespace mul_action_hom

instance : has_coe_to_fun (X →[M] Y) :=
instance : has_coe_to_fun (X →[M'] Y) :=
⟨_, λ c, c.to_fun⟩

variables {M X Y}
variables {M M' X Y}

@[simp] lemma map_smul (f : X →[M] Y) (m : M) (x : X) : f (m • x) = m • f x :=
@[simp] lemma map_smul (f : X →[M'] Y) (m : M') (x : X) : f (m • x) = m • f x :=
f.map_smul' m x

@[ext] theorem ext : ∀ {f g : X →[M] Y}, (∀ x, f x = g x) → f = g
@[ext] theorem ext : ∀ {f g : X →[M'] Y}, (∀ x, f x = g x) → f = g
| ⟨f, _⟩ ⟨g, _⟩ H := by { congr' 1 with x, exact H x }

theorem ext_iff {f g : X →[M] Y} : f = g ↔ ∀ x, f x = g x :=
theorem ext_iff {f g : X →[M'] Y} : f = g ↔ ∀ x, f x = g x :=
⟨λ H x, by rw H, ext⟩

variables (M) {X}
variables (M M') {X}

/-- The identity map as an equivariant map. -/
protected def id : X →[M] X :=
protected def id : X →[M'] X :=
⟨id, λ _ _, rfl⟩

@[simp] lemma id_apply (x : X) : mul_action_hom.id M x = x := rfl
@[simp] lemma id_apply (x : X) : mul_action_hom.id M' x = x := rfl

variables {M X Y Z}
variables {M M' X Y Z}

/-- Composition of two equivariant maps. -/
def comp (g : Y →[M] Z) (f : X →[M] Y) : X →[M] Z :=
def comp (g : Y →[M'] Z) (f : X →[M'] Y) : X →[M'] Z :=
⟨g ∘ f, λ m x, calc
g (f (m • x)) = g (m • f x) : by rw f.map_smul
... = m • g (f x) : g.map_smul _ _⟩

@[simp] lemma comp_apply (g : Y →[M] Z) (f : X →[M] Y) (x : X) : g.comp f x = g (f x) := rfl
@[simp] lemma comp_apply (g : Y →[M'] Z) (f : X →[M'] Y) (x : X) : g.comp f x = g (f x) := rfl

@[simp] lemma id_comp (f : X →[M] Y) : (mul_action_hom.id M).comp f = f :=
@[simp] lemma id_comp (f : X →[M'] Y) : (mul_action_hom.id M').comp f = f :=
ext $ λ x, by rw [comp_apply, id_apply]

@[simp] lemma comp_id (f : X →[M] Y) : f.comp (mul_action_hom.id M) = f :=
@[simp] lemma comp_id (f : X →[M'] Y) : f.comp (mul_action_hom.id M') = f :=
ext $ λ x, by rw [comp_apply, id_apply]

local attribute [instance] mul_action.regular
Expand Down
22 changes: 16 additions & 6 deletions src/algebra/module/submodule.lean
Expand Up @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Nathaniel Thomas, Jeremy Avigad, Johannes Hölzl, Mario Carneiro
-/
import algebra.module.linear_map
import group_theory.group_action.sub_mul_action
/-!
# Submodules of a module
Expand Down Expand Up @@ -32,12 +33,14 @@ set_option old_structure_cmd true
This is a sufficient condition for the subset of vectors in the submodule
to themselves form a module. -/
structure submodule (R : Type u) (M : Type v) [semiring R]
[add_comm_monoid M] [semimodule R M] extends add_submonoid M : Type v :=
(smul_mem' : ∀ (c:R) {x}, x ∈ carrier → c • x ∈ carrier)
[add_comm_monoid M] [semimodule R M] extends add_submonoid M, sub_mul_action R M : Type v.

/-- Reinterpret a `submodule` as an `add_submonoid`. -/
add_decl_doc submodule.to_add_submonoid

/-- Reinterpret a `submodule` as an `sub_mul_action`. -/
add_decl_doc submodule.to_sub_mul_action

namespace submodule

variables [semiring R] [add_comm_monoid M] [semimodule R M]
Expand Down Expand Up @@ -72,6 +75,13 @@ theorem to_add_submonoid_injective :
@[simp] theorem to_add_submonoid_eq : p.to_add_submonoid = q.to_add_submonoid ↔ p = q :=
to_add_submonoid_injective.eq_iff

theorem to_sub_mul_action_injective :
injective (to_sub_mul_action : submodule R M → sub_mul_action R M) :=
λ p q h, ext'_iff.2 $ sub_mul_action.ext'_iff.1 h

@[simp] theorem to_sub_mul_action_eq : p.to_sub_mul_action = q.to_sub_mul_action ↔ p = q :=
to_sub_mul_action_injective.eq_iff

end submodule

namespace submodule
Expand Down Expand Up @@ -105,7 +115,7 @@ lemma sum_smul_mem {t : finset ι} {f : ι → M} (r : ι → R)
submodule.sum_mem _ (λ i hi, submodule.smul_mem _ _ (hyp i hi))

@[simp] lemma smul_mem_iff' (u : units R) : (u:R) • x ∈ p ↔ x ∈ p :=
⟨λ h, by simpa only [smul_smul, u.inv_mul, one_smul] using p.smul_mem ↑u⁻¹ h, p.smul_mem u⟩
p.to_sub_mul_action.smul_mem_iff' u

instance : has_add p := ⟨λx y, ⟨x.1 + y.1, add_mem _ x.2 y.2⟩⟩
instance : has_zero p := ⟨⟨0, zero_mem _⟩⟩
Expand Down Expand Up @@ -133,7 +143,7 @@ instance : add_comm_monoid p :=
{ add := (+), zero := 0, .. p.to_add_submonoid.to_add_comm_monoid }

instance : semimodule R p :=
by refine {smul := (•), ..};
by refine {smul := (•), ..p.to_sub_mul_action.mul_action, ..};
{ intros, apply set_coe.ext, simp [smul_add, add_smul, mul_smul] }

/-- Embedding of a submodule `p` to the ambient space `M`. -/
Expand All @@ -153,7 +163,7 @@ variables {semimodule_M : semimodule R M}
variables (p p' : submodule R M)
variables {r : R} {x y : M}

lemma neg_mem (hx : x ∈ p) : -x ∈ p := by rw ← neg_one_smul R; exact p.smul_mem _ hx
lemma neg_mem (hx : x ∈ p) : -x ∈ p := p.to_sub_mul_action.neg_mem hx

/-- Reinterpret a submodule as an additive subgroup. -/
def to_add_subgroup : add_subgroup M :=
Expand Down Expand Up @@ -188,7 +198,7 @@ variables [division_ring R] [add_comm_group M] [module R M]
variables (p : submodule R M) {r : R} {x y : M}

theorem smul_mem_iff (r0 : r ≠ 0) : r • x ∈ p ↔ x ∈ p :=
p.smul_mem_iff' (units.mk0 r r0)
p.to_sub_mul_action.smul_mem_iff r0

end submodule

Expand Down
156 changes: 156 additions & 0 deletions src/group_theory/group_action/sub_mul_action.lean
@@ -0,0 +1,156 @@
/-
Copyright (c) 2020 Eric Wieser. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Eric Wieser
-/
import group_theory.group_action.basic
import algebra.group_action_hom
import algebra.module.basic
/-!
# Sets invariant to a `mul_action`
In this file we define `sub_mul_action R M`; a subset of a `mul_action M` which is closed with
respect to scalar multiplication.
For most uses, typically `submodule R M` is more powerful.
## Tags
submodule, mul_action
-/

open function

universes u v
variables {R : Type u} {M : Type v}

set_option old_structure_cmd true

/-- A sub_mul_action is a set which is closed under scalar multiplication. -/
structure sub_mul_action (R : Type u) (M : Type v) [has_scalar R M] : Type v :=
(carrier : set M)
(smul_mem' : ∀ (c : R) {x : M}, x ∈ carrier → c • x ∈ carrier)

namespace sub_mul_action

variables [has_scalar R M]

instance : has_coe_t (sub_mul_action R M) (set M) := ⟨λ s, s.carrier⟩
instance : has_mem M (sub_mul_action R M) := ⟨λ x p, x ∈ (p : set M)⟩
instance : has_coe_to_sort (sub_mul_action R M) := ⟨_, λ p, {x : M // x ∈ p}⟩

instance : has_top (sub_mul_action R M) :=
⟨{ carrier := set.univ, smul_mem' := λ _ _ _, set.mem_univ _ }⟩

instance : has_bot (sub_mul_action R M) :=
⟨{ carrier := ∅, smul_mem' := λ c, set.not_mem_empty}⟩

instance : inhabited (sub_mul_action R M) := ⟨⊥⟩

variables (p q : sub_mul_action R M)

@[simp, norm_cast] theorem coe_sort_coe : ↥(p : set M) = p := rfl

variables {p q}

protected theorem «exists» {q : p → Prop} : (∃ x, q x) ↔ (∃ x ∈ p, q ⟨x, ‹_›⟩) := set_coe.exists

protected theorem «forall» {q : p → Prop} : (∀ x, q x) ↔ (∀ x ∈ p, q ⟨x, ‹_›⟩) := set_coe.forall

theorem coe_injective : injective (coe : sub_mul_action R M → set M) :=
λ p q h, by cases p; cases q; congr'

@[simp, norm_cast] theorem coe_set_eq : (p : set M) = q ↔ p = q := coe_injective.eq_iff

theorem ext'_iff : p = q ↔ (p : set M) = q := coe_set_eq.symm

@[ext] theorem ext (h : ∀ x, x ∈ p ↔ x ∈ q) : p = q := coe_injective $ set.ext h

end sub_mul_action

namespace sub_mul_action

section has_scalar

variables [has_scalar R M]
variables (p : sub_mul_action R M)
variables {r : R} {x : M}

@[simp] theorem mem_coe : x ∈ (p : set M) ↔ x ∈ p := iff.rfl

lemma smul_mem (r : R) (h : x ∈ p) : r • x ∈ p := p.smul_mem' r h

instance : has_scalar R p :=
{ smul := λ c x, ⟨c • x.1, smul_mem _ c x.2⟩ }

variables {p}
@[simp, norm_cast] lemma coe_eq_coe {x y : p} : (x : M) = y ↔ x = y := subtype.ext_iff_val.symm
@[simp, norm_cast] lemma coe_smul (r : R) (x : p) : ((r • x : p) : M) = r • ↑x := rfl
@[simp, norm_cast] lemma coe_mk (x : M) (hx : x ∈ p) : ((⟨x, hx⟩ : p) : M) = x := rfl
@[simp] lemma coe_mem (x : p) : (x : M) ∈ p := x.2

variables {p}

@[simp] protected lemma eta (x : p) (hx : (x : M) ∈ p) : (⟨x, hx⟩ : p) = x := subtype.eta x hx

variables (p)

/-- Embedding of a submodule `p` to the ambient space `M`. -/
protected def subtype : p →[R] M :=
by refine {to_fun := coe, ..}; simp [coe_smul]

@[simp] theorem subtype_apply (x : p) : p.subtype x = x := rfl

lemma subtype_eq_val : ((sub_mul_action.subtype p) : p → M) = subtype.val := rfl

end has_scalar

section mul_action

variables [monoid R]

variables [mul_action R M]
variables (p : sub_mul_action R M)
variables {r : R} {x : M}

@[simp] lemma smul_mem_iff' (u : units R) : (u : R) • x ∈ p ↔ x ∈ p :=
⟨λ h, by simpa only [smul_smul, u.inv_mul, one_smul] using p.smul_mem ↑u⁻¹ h, p.smul_mem u⟩

/- If the scalar product forms a mul_action, then the subset inherits this action -/
instance : mul_action R p :=
{ smul := (•),
one_smul := λ x, subtype.ext $ one_smul _ x,
mul_smul := λ c₁ c₂ x, subtype.ext $ mul_smul c₁ c₂ x }

end mul_action

section add_comm_group

variables [ring R] [add_comm_group M]
variables [semimodule R M]
variables (p p' : sub_mul_action R M)
variables {r : R} {x y : M}

lemma neg_mem (hx : x ∈ p) : -x ∈ p := by { rw ← neg_one_smul R, exact p.smul_mem _ hx }

@[simp] lemma neg_mem_iff : -x ∈ p ↔ x ∈ p :=
⟨λ h, by { rw ←neg_neg x, exact neg_mem _ h}, neg_mem _⟩

instance : has_neg p := ⟨λx, ⟨-x.1, neg_mem _ x.2⟩⟩

@[simp, norm_cast] lemma coe_neg (x : p) : ((-x : p) : M) = -x := rfl

end add_comm_group

end sub_mul_action

namespace sub_mul_action

variables [division_ring R] [add_comm_group M] [module R M]
variables (p : sub_mul_action R M) {r : R} {x y : M}

theorem smul_mem_iff (r0 : r ≠ 0) : r • x ∈ p ↔ x ∈ p :=
p.smul_mem_iff' (units.mk0 r r0)

end sub_mul_action

0 comments on commit f6273d4

Please sign in to comment.