Skip to content

Commit

Permalink
feat(data/equiv/algebra): change mul_equiv field to map_mul (#1287)
Browse files Browse the repository at this point in the history
* feat(data/equiv/algebra): bundle field for mul_equiv

* adding docs

* Update src/data/equiv/algebra.lean

* Update src/data/equiv/algebra.lean

Co-Authored-By: sgouezel <sebastien.gouezel@univ-rennes1.fr>
  • Loading branch information
2 people authored and mergify[bot] committed Jul 31, 2019
1 parent 9d589d7 commit badeb48
Show file tree
Hide file tree
Showing 6 changed files with 219 additions and 47 deletions.
2 changes: 1 addition & 1 deletion src/category_theory/endomorphism.lean
Expand Up @@ -68,7 +68,7 @@ def units_End_eqv_Aut : units (End X) ≃* Aut X :=
inv_fun := λ f, ⟨f.1, f.2, f.4, f.3⟩,
left_inv := λ ⟨f₁, f₂, f₃, f₄⟩, rfl,
right_inv := λ ⟨f₁, f₂, f₃, f₄⟩, rfl,
hom := λ f g, by rcases f; rcases g; refl }
map_mul' := λ f g, by rcases f; rcases g; refl }

end Aut

Expand Down
242 changes: 207 additions & 35 deletions src/data/equiv/algebra.lean
Expand Up @@ -2,17 +2,39 @@
Copyright (c) 2018 Johannes Hölzl. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Johannes Hölzl
-/

import data.equiv.basic algebra.field

/-!
# equivs in the algebraic hierarchy
The role of this file is twofold. In the first part there are theorems of the following
form: if α has a group structure and α ≃ β then β has a group structure, and
similarly for monoids, semigroups, rings, integral domains, fields and so on.
In the second part there are extensions of equiv called add_equiv,
mul_equiv, and ring_equiv, which are datatypes representing isomorphisms
of monoids, groups and rings.
of add_monoids/add_groups, monoids/groups and rings.
## Notations
The extended equivs all have coercions to functions, and the coercions are the canonical
notation when treating the isomorphisms as maps.
## Implementation notes
Bundling structures means that many things turn into definitions, meaning that to_additive
cannot do much work for us, and conversely that we have to do a lot of naming for it.
The fields for mul_equiv and add_equiv now avoid the unbundled `is_mul_hom` and `is_add_hom`,
as these are deprecated. However ring_equiv still relies on `is_ring_hom`; this should
be rewritten in future.
## Tags
equiv, mul_equiv, add_equiv, ring_equiv
-/
import data.equiv.basic algebra.field

universes u v w x
variables {α : Type u} {β : Type v} {γ : Type w} {δ : Type x}
Expand Down Expand Up @@ -199,77 +221,224 @@ protected def discrete_field [discrete_field β] : discrete_field α :=
end instances
end equiv

set_option old_structure_cmd true

/-- mul_equiv α β is the type of an equiv α ≃ β which preserves multiplication. -/
structure mul_equiv (α β : Type*) [has_mul α] [has_mul β] extends α ≃ β :=
(hom : is_mul_hom to_fun)
(map_mul' : ∀ x y : α, to_fun (x * y) = to_fun x * to_fun y)

/-- add_equiv α β is the type of an equiv α ≃ β which preserves addition. -/
structure add_equiv (α β : Type*) [has_add α] [has_add β] extends α ≃ β :=
(hom : is_add_hom to_fun)
(map_add' : ∀ x y : α, to_fun (x + y) = to_fun x + to_fun y)

attribute [to_additive add_equiv] mul_equiv
attribute [to_additive add_equiv.cases_on] mul_equiv.cases_on
attribute [to_additive add_equiv.has_sizeof_inst] mul_equiv.has_sizeof_inst
attribute [to_additive add_equiv.inv_fun] mul_equiv.inv_fun
attribute [to_additive add_equiv.left_inv] mul_equiv.left_inv
attribute [to_additive add_equiv.mk] mul_equiv.mk
attribute [to_additive add_equiv.mk.inj] mul_equiv.mk.inj
attribute [to_additive add_equiv.mk.inj_arrow] mul_equiv.mk.inj_arrow
attribute [to_additive add_equiv.mk.inj_eq] mul_equiv.mk.inj_eq
attribute [to_additive add_equiv.mk.sizeof_spec] mul_equiv.mk.sizeof_spec
attribute [to_additive add_equiv.map_add'] mul_equiv.map_mul'
attribute [to_additive add_equiv.no_confusion] mul_equiv.no_confusion
attribute [to_additive add_equiv.no_confusion_type] mul_equiv.no_confusion_type
attribute [to_additive add_equiv.rec] mul_equiv.rec
attribute [to_additive add_equiv.rec_on] mul_equiv.rec_on
attribute [to_additive add_equiv.right_inv] mul_equiv.right_inv
attribute [to_additive add_equiv.sizeof] mul_equiv.sizeof
attribute [to_additive add_equiv.to_equiv] mul_equiv.to_equiv
attribute [to_additive add_equiv.hom] mul_equiv.hom
attribute [to_additive add_equiv.to_fun] mul_equiv.to_fun

infix ` ≃* `:25 := mul_equiv
infix ` ≃+ `:25 := add_equiv

namespace mul_equiv

@[to_additive add_equiv.has_coe_to_fun]
instance {α β} [has_mul α] [has_mul β] : has_coe_to_fun (α ≃* β) := ⟨_, mul_equiv.to_fun⟩

variables [has_mul α] [has_mul β] [has_mul γ]

@[to_additive add_mul.is_add_hom]
instance (h : α ≃* β) : is_mul_hom h.to_equiv := h.hom
/-- A multiplicative isomorphism preserves multiplication (canonical form). -/
def map_mul (f : α ≃* β) : ∀ x y : α, f (x * y) = f x * f y := f.map_mul'

/-- A multiplicative isomorphism preserves multiplication (deprecated). -/
instance (h : α ≃* β) : is_mul_hom h := ⟨h.map_mul⟩

/-- The identity map is a multiplicative isomorphism. -/
@[refl] def refl (α : Type*) [has_mul α] : α ≃* α :=
{ hom := λ _ _,rfl,
{ map_mul' := λ _ _,rfl,
..equiv.refl _}

attribute [to_additive add_equiv.refl._proof_3] mul_equiv.refl._proof_3
attribute [to_additive add_equiv.refl] mul_equiv.refl

/-- The inverse of an isomorphism is an isomorphism. -/
@[symm] def symm (h : α ≃* β) : β ≃* α :=
{ hom := ⟨λ n₁ n₂, function.injective_of_left_inverse h.left_inv begin
rw h.hom.map_mul, unfold equiv.symm, rw [h.right_inv, h.right_inv, h.right_inv], end
{ map_mul' := λ n₁ n₂, function.injective_of_left_inverse h.left_inv begin
show h.to_equiv (h.to_equiv.symm (n₁ * n₂)) =
h ((h.to_equiv.symm n₁) * (h.to_equiv.symm n₂)),
rw h.map_mul,
show _ = h.to_equiv (_) * h.to_equiv (_),
rw [h.to_equiv.apply_symm_apply, h.to_equiv.apply_symm_apply, h.to_equiv.apply_symm_apply], end,
..h.to_equiv.symm}

@[simp] theorem to_equiv_symm (f : α ≃* β) : f.symm.to_equiv = f.to_equiv.symm := rfl

/-- Transitivity of multiplication-preserving isomorphisms -/
@[trans] def trans (h1 : α ≃* β) (h2 : β ≃* γ) : (α ≃* γ) :=
{ map_mul' := λ x y, show h2 (h1 (x * y)) = h2 (h1 x) * h2 (h1 y),
by rw [h1.map_mul, h2.map_mul],
..h1.to_equiv.trans h2.to_equiv }

/-- e.right_inv in canonical form -/
@[simp] def apply_symm_apply (e : α ≃* β) : ∀ (y : β), e (e.symm y) = y :=
equiv.apply_symm_apply (e.to_equiv)

/-- e.left_inv in canonical form -/
@[simp] def symm_apply_apply (e : α ≃* β) : ∀ (x : α), e.symm (e x) = x :=
equiv.symm_apply_apply (e.to_equiv)

/-- a multiplicative equiv of monoids sends 1 to 1 (and is hence a monoid isomorphism) -/
@[simp] def map_one {α β} [monoid α] [monoid β] (h : α ≃* β) : h 1 = 1 :=
by rw [←mul_one (h 1), ←h.apply_symm_apply 1, ←h.map_mul, one_mul]

/-- A multiplicative bijection between two monoids is an isomorphism. -/
def to_monoid_hom {α β} [monoid α] [monoid β] (h : α ≃* β) : (α →* β) :=
{ to_fun := h,
map_mul' := h.map_mul,
map_one' := h.map_one }

/-- A multiplicative bijection between two monoids is a monoid hom
(deprecated -- use to_monoid_hom). -/
instance is_monoid_hom {α β} [monoid α] [monoid β] (h : α ≃* β) : is_monoid_hom h :=
⟨h.map_one⟩

/-- A multiplicative bijection between two groups is a group hom
(deprecated -- use to_monoid_hom). -/
instance is_group_hom {α β} [group α] [group β] (h : α ≃* β) :
is_group_hom h := { map_mul := h.map_mul }

end mul_equiv

namespace add_equiv

variables [has_add α] [has_add β] [has_add γ]

/-- An additive isomorphism preserves addition (canonical form). -/
def map_add (f : α ≃+ β) : ∀ x y : α, f (x + y) = f x + f y := f.map_add'

attribute [to_additive add_equiv.map_add] mul_equiv.map_mul
attribute [to_additive add_equiv.map_add.equations._eqn_1] mul_equiv.map_mul.equations._eqn_1

/-- A additive isomorphism preserves multiplication (deprecated). -/
instance (h : α ≃+ β) : is_add_hom h := ⟨h.map_add⟩

/-- The identity map is an additive isomorphism. -/
@[refl] def refl (α : Type*) [has_add α] : α ≃+ α :=
{ map_add' := λ _ _,rfl,
..equiv.refl _}

attribute [to_additive add_equiv.refl] mul_equiv.refl
attribute [to_additive add_equiv.refl._proof_1] mul_equiv.refl._proof_1
attribute [to_additive add_equiv.refl._proof_2] mul_equiv.refl._proof_2
attribute [to_additive add_equiv.refl._proof_3] mul_equiv.refl._proof_3
attribute [to_additive add_equiv.refl.equations._eqn_1] mul_equiv.refl.equations._eqn_1

/-- The inverse of an isomorphism is an isomorphism. -/
@[symm] def symm (h : α ≃+ β) : β ≃+ α :=
{ map_add' := λ n₁ n₂, function.injective_of_left_inverse h.left_inv begin
show h.to_equiv (h.to_equiv.symm (n₁ + n₂)) =
h ((h.to_equiv.symm n₁) + (h.to_equiv.symm n₂)),
rw h.map_add,
show _ = h.to_equiv (_) + h.to_equiv (_),
rw [h.to_equiv.apply_symm_apply, h.to_equiv.apply_symm_apply, h.to_equiv.apply_symm_apply], end,
..h.to_equiv.symm}

attribute [to_additive add_equiv.symm] mul_equiv.symm
attribute [to_additive add_equiv.symm._proof_1] mul_equiv.symm._proof_1
attribute [to_additive add_equiv.symm._proof_2] mul_equiv.symm._proof_2
attribute [to_additive add_equiv.symm._proof_3] mul_equiv.symm._proof_3
attribute [to_additive add_equiv.symm] mul_equiv.symm
attribute [to_additive add_equiv.symm.equations._eqn_1] mul_equiv.symm.equations._eqn_1

@[trans] def trans (h1 : α ≃* β) (h2 : β ≃* γ) : (α ≃* γ) :=
{ hom := is_mul_hom.comp _ _,
..equiv.trans h1.to_equiv h2.to_equiv }
@[simp] theorem to_equiv_symm (f : α ≃+ β) : f.symm.to_equiv = f.to_equiv.symm := rfl

attribute [to_additive add_equiv.to_equiv_symm] mul_equiv.to_equiv_symm

/-- Transitivity of addition-preserving isomorphisms -/
@[trans] def trans (h1 : α ≃+ β) (h2 : β ≃+ γ) : (α ≃+ γ) :=
{ map_add' := λ x y, show h2 (h1 (x + y)) = h2 (h1 x) + h2 (h1 y),
by rw [h1.map_add, h2.map_add],
..h1.to_equiv.trans h2.to_equiv }

attribute [to_additive add_equiv.trans] mul_equiv.trans
attribute [to_additive add_equiv.trans._proof_1] mul_equiv.trans._proof_1
attribute [to_additive add_equiv.trans._proof_2] mul_equiv.trans._proof_2
attribute [to_additive add_equiv.trans._proof_3] mul_equiv.trans._proof_3
attribute [to_additive add_equiv.trans] mul_equiv.trans
attribute [to_additive add_equiv.trans.equations._eqn_1] mul_equiv.trans.equations._eqn_1

end mul_equiv
/-- e.right_inv in canonical form -/
def apply_symm_apply (e : α ≃+ β) : ∀ (y : β), e (e.symm y) = y :=
equiv.apply_symm_apply (e.to_equiv)

attribute [to_additive add_equiv.apply_symm_apply] mul_equiv.apply_symm_apply
attribute [to_additive add_equiv.apply_symm_apply.equations._eqn_1] mul_equiv.apply_symm_apply.equations._eqn_1

/-- e.left_inv in canonical form -/
def symm_apply_apply (e : α ≃+ β) : ∀ (x : α), e.symm (e x) = x :=
equiv.symm_apply_apply (e.to_equiv)

attribute [to_additive add_equiv.symm_apply_apply] mul_equiv.symm_apply_apply
attribute [to_additive add_equiv.symm_apply_apply.equations._eqn_1] mul_equiv.symm_apply_apply.equations._eqn_1

/-- an additive equiv of monoids sends 0 to 0 (and is hence an `add_monoid` isomorphism) -/
def map_zero {α β} [add_monoid α] [add_monoid β] (h : α ≃+ β) : h 0 = 0 :=
by rw [←add_zero (h 0), ←h.apply_symm_apply 0, ←h.map_add, zero_add]

attribute [to_additive add_equiv.map_zero] mul_equiv.map_one
attribute [to_additive add_equiv.map_zero.equations._eqn_1] mul_equiv.map_one.equations._eqn_1

/-- An additive bijection between two add_monoids is an isomorphism. -/
def to_add_monoid_hom {α β} [add_monoid α] [add_monoid β] (h : α ≃+ β) : (α →+ β) :=
{ to_fun := h,
map_add' := h.map_add,
map_zero' := h.map_zero }

attribute [to_additive add_equiv.to_add_monoid_hom] mul_equiv.to_monoid_hom
attribute [to_additive add_equiv.to_add_monoid_hom._proof_1] mul_equiv.to_monoid_hom._proof_1
attribute [to_additive add_equiv.to_add_monoid_hom.equations._eqn_1]
mul_equiv.to_monoid_hom.equations._eqn_1

/-- an additive bijection between two add_monoids is an add_monoid hom
(deprecated -- use to_add_monoid_hom) -/
instance is_add_monoid_hom {α β} [add_monoid α] [add_monoid β] (h : α ≃+ β) : is_add_monoid_hom h :=
⟨h.map_zero⟩

attribute [to_additive add_equiv.is_add_monoid_hom] mul_equiv.is_monoid_hom
attribute [to_additive add_equiv.is_add_monoid_hom.equations._eqn_1]
mul_equiv.is_monoid_hom.equations._eqn_1

/-- An additive bijection between two add_groups is an add_group hom
(deprecated -- use to_monoid_hom). -/
instance is_add_group_hom {α β} [add_group α] [add_group β] (h : α ≃+ β) :
is_add_group_hom h := { map_add := h.map_add }

-- equiv of monoids
@[to_additive add_equiv.is_add_monoid_hom]
instance mul_equiv.is_monoid_hom [monoid α] [monoid β] (h : α ≃* β) : is_monoid_hom h.to_equiv :=
{ map_one := by rw [← mul_one (h.to_equiv 1), ← h.to_equiv.apply_symm_apply 1,
← is_mul_hom.map_mul h.to_equiv, one_mul] }
attribute [to_additive add_equiv.is_add_group_hom] mul_equiv.is_group_hom
attribute [to_additive add_equiv.is_add_group_hom.equations._eqn_1]
mul_equiv.is_group_hom.equations._eqn_1

-- equiv of groups
@[to_additive add_equiv.is_add_group_hom]
instance mul_equiv.is_group_hom [group α] [group β] (h : α ≃* β) :
is_group_hom h.to_equiv := { ..h.hom }
end add_equiv

namespace units

variables [monoid α] [monoid β] [monoid γ]
(f : α → β) (g : β → γ) [is_monoid_hom f] [is_monoid_hom g]

def map_equiv (h : α ≃* β) : units α ≃* units β :=
{ to_fun := map h.to_equiv,
inv_fun := map h.symm.to_equiv,
{ to_fun := map h,
inv_fun := map h.symm,
left_inv := λ u, ext $ h.left_inv u,
right_inv := λ u, ext $ h.right_inv u,
hom := λ a b, units.ext $ is_mul_hom.map_mul h.to_equiv a b}
map_mul' := λ a b, units.ext $ h.map_mul a b}

end units

Expand All @@ -283,23 +452,26 @@ namespace ring_equiv
variables [ring α] [ring β] [ring γ]

instance (h : α ≃r β) : is_ring_hom h.to_equiv := h.hom
instance ring_equiv.is_ring_hom' (h : α ≃r β) : is_ring_hom h.to_fun := h.hom

def to_mul_equiv (e : α ≃r β) : α ≃* β :=
{ hom := by apply_instance, .. e.to_equiv }
{ map_mul' := e.hom.map_mul, .. e.to_equiv }

def to_add_equiv (e : α ≃r β) : α ≃+ β :=
{ hom := by apply_instance, .. e.to_equiv }
{ map_add' := e.hom.map_add, .. e.to_equiv }

protected def refl (α : Type*) [ring α] : α ≃r α :=
{ hom := is_ring_hom.id, .. equiv.refl α }

protected def symm {α β : Type*} [ring α] [ring β] (e : α ≃r β) : β ≃r α :=
{ hom := { .. e.to_mul_equiv.symm.is_monoid_hom, .. e.to_add_equiv.symm.hom },
{ hom := { map_one := e.to_mul_equiv.symm.map_one,
map_mul := e.to_mul_equiv.symm.map_mul,
map_add := e.to_add_equiv.symm.map_add },
.. e.to_equiv.symm }

protected def trans {α β γ : Type*} [ring α] [ring β] [ring γ]
(e₁ : α ≃r β) (e₂ : β ≃r γ) : α ≃r γ :=
{ hom := is_ring_hom.comp _ _, .. e₁.1.trans e₂.1 }
{ hom := is_ring_hom.comp _ _, .. e₁.to_equiv.trans e₂.to_equiv }

instance symm.is_ring_hom {e : α ≃r β} : is_ring_hom e.to_equiv.symm := hom e.symm

Expand Down
8 changes: 4 additions & 4 deletions src/data/mv_polynomial.lean
Expand Up @@ -983,14 +983,14 @@ def ring_equiv_of_equiv (e : β ≃ γ) : mv_polynomial β α ≃r mv_polynomial
hom := rename.is_ring_hom e }

def ring_equiv_congr [comm_ring γ] (e : α ≃r γ) : mv_polynomial β α ≃r mv_polynomial β γ :=
{ to_fun := map e.to_fun,
inv_fun := map e.symm.to_fun,
{ to_fun := map e.to_equiv,
inv_fun := map e.symm.to_equiv,
left_inv := assume p,
have (e.symm.to_equiv.to_fun ∘ e.to_equiv.to_fun) = id,
have (e.symm.to_equiv ∘ e.to_equiv) = id,
{ ext a, exact e.to_equiv.symm_apply_apply a },
by simp only [map_map, this, map_id],
right_inv := assume p,
have (e.to_equiv.to_fun ∘ e.symm.to_equiv.to_fun) = id,
have (e.to_equiv ∘ e.symm.to_equiv) = id,
{ ext a, exact e.to_equiv.apply_symm_apply a },
by simp only [map_map, this, map_id],
hom := map.is_ring_hom e.to_fun }
Expand Down
2 changes: 1 addition & 1 deletion src/linear_algebra/basic.lean
Expand Up @@ -1587,7 +1587,7 @@ def general_linear_equiv : general_linear_group α β ≃* (β ≃ₗ[α] β) :=
cases f,
congr
end,
hom := λ x y, by {ext, refl} }
map_mul' := λ x y, by {ext, refl} }

@[simp] lemma general_linear_equiv_to_linear_map (f : general_linear_group α β) :
((general_linear_equiv α β).to_equiv f).to_linear_map = f.val :=
Expand Down
10 changes: 5 additions & 5 deletions src/ring_theory/free_comm_ring.lean
Expand Up @@ -265,21 +265,21 @@ end

def subsingleton_equiv_free_comm_ring [subsingleton α] :
free_ring α ≃r free_comm_ring α :=
{ to_equiv := @functor.map_equiv _ _ free_abelian_group _ _ $ multiset.subsingleton_equiv α,
hom :=
{ hom :=
begin
delta functor.map_equiv,
rw congr_arg is_ring_hom _,
work_on_goal 2 { symmetry, exact coe_eq α },
apply_instance
end }
end,
..@functor.map_equiv _ _ free_abelian_group _ _ $ multiset.subsingleton_equiv α }

instance [subsingleton α] : comm_ring (free_ring α) :=
{ mul_comm := λ x y,
by rw [← (subsingleton_equiv_free_comm_ring α).left_inv (y * x),
is_ring_hom.map_mul ((subsingleton_equiv_free_comm_ring α).to_equiv).to_fun,
is_ring_hom.map_mul ((subsingleton_equiv_free_comm_ring α)).to_fun,
mul_comm,
← is_ring_hom.map_mul ((subsingleton_equiv_free_comm_ring α).to_equiv).to_fun,
← is_ring_hom.map_mul ((subsingleton_equiv_free_comm_ring α)).to_fun,
(subsingleton_equiv_free_comm_ring α).left_inv],
.. free_ring.ring α }

Expand Down
2 changes: 1 addition & 1 deletion src/ring_theory/noetherian.lean
Expand Up @@ -393,7 +393,7 @@ instance is_noetherian_ring_range {R} [comm_ring R] {S} [comm_ring S] (f : R →

theorem is_noetherian_ring_of_ring_equiv (R) [comm_ring R] {S} [comm_ring S]
(f : R ≃r S) [is_noetherian_ring R] : is_noetherian_ring S :=
is_noetherian_ring_of_surjective R S f.1 f.1.surjective
is_noetherian_ring_of_surjective R S f.1 f.to_equiv.surjective

namespace is_noetherian_ring

Expand Down

0 comments on commit badeb48

Please sign in to comment.