Skip to content

Commit

Permalink
feat(algebra/module/basic): module rat E is a subsingleton (#9570)
Browse files Browse the repository at this point in the history
* allow different (semi)rings in `add_monoid_hom.map_int_cast_smul` and `add_monoid_hom.map_nat_cast_smul`;
* add `add_monoid_hom.map_inv_int_cast_smul` and `add_monoid_hom.map_inv_nat_cast_smul`;
* allow different division rings in `add_monoid_hom.map_rat_cast_smul`, drop `char_zero` assumption;
* prove `subsingleton (module rat M)`;
* add a few convenience lemmas.



Co-authored-by: Johan Commelin <johan@commelin.net>
  • Loading branch information
urkud and jcommelin committed Oct 8, 2021
1 parent eb3595e commit c400677
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 39 deletions.
82 changes: 60 additions & 22 deletions src/algebra/module/basic.lean
Expand Up @@ -121,7 +121,7 @@ def module.to_add_monoid_End : R →+* add_monoid.End M :=
map_add' := λ x y, add_monoid_hom.ext $ λ r, by simp [add_smul],
..distrib_mul_action.to_add_monoid_End R M }

/-- A convenience alias for `module.to_add_monoid_End` as a `monoid_hom`, usually to allow the
/-- A convenience alias for `module.to_add_monoid_End` as an `add_monoid_hom`, usually to allow the
use of `add_monoid_hom.flip`. -/
def smul_add_hom : R →+ M →+ M :=
(module.to_add_monoid_End R M).to_add_monoid_hom
Expand Down Expand Up @@ -380,40 +380,78 @@ lemma map_int_module_smul [add_comm_group M] [add_comm_group M₂]
(f : M →+ M₂) (x : ℤ) (a : M) : f (x • a) = x • f a :=
by simp only [f.map_gsmul]

lemma map_int_cast_smul
[ring R] [add_comm_group M] [add_comm_group M₂] [module R M] [module R M₂]
(f : M →+ M₂) (x : ℤ) (a : M) : f ((x : R) • a) = (x : R) • f a :=
lemma map_int_cast_smul [add_comm_group M] [add_comm_group M₂]
(f : M →+ M₂) (R S : Type*) [ring R] [ring S] [module R M] [module S M₂]
(x : ℤ) (a : M) : f ((x : R) • a) = (x : S) • f a :=
by simp only [←gsmul_eq_smul_cast, f.map_gsmul]

lemma map_nat_cast_smul
[semiring R] [add_comm_monoid M] [add_comm_monoid M₂]
[module R M] [module R M₂] (f : M →+ M₂) (x : ℕ) (a : M) :
f ((x : R) • a) = (x : R) • f a :=
lemma map_nat_cast_smul [add_comm_monoid M] [add_comm_monoid M₂] (f : M →+ M₂)
(R S : Type*) [semiring R] [semiring S] [module R M] [module S M₂] (x : ℕ) (a : M) :
f ((x : R) • a) = (x : S) • f a :=
by simp only [←nsmul_eq_smul_cast, f.map_nsmul]

lemma map_rat_cast_smul {R : Type*} [division_ring R] [char_zero R]
{E : Type*} [add_comm_group E] [module R E] {F : Type*} [add_comm_group F] [module R F]
(f : E →+ F) (c : ℚ) (x : E) :
f ((c : R) • x) = (c : R) • f x :=
lemma map_inv_int_cast_smul {E F : Type*} [add_comm_group E] [add_comm_group F] (f : E →+ F)
(R S : Type*) [division_ring R] [division_ring S] [module R E] [module S F]
(n : ) (x : E) :
f ((n⁻¹ : R) • x) = (n⁻¹ : S) • f x :=
begin
have : ∀ (x : E) (n : ℕ), 0 < n → f (((n⁻¹ : ℚ) : R) • x) = ((n⁻¹ : ℚ) : R) • f x,
{ intros x n hn,
replace hn : (n : R) ≠ 0 := nat.cast_ne_zero.2 (ne_of_gt hn),
conv_rhs { congr, skip, rw [← one_smul R x, ← mul_inv_cancel hn, mul_smul] },
rw [f.map_nat_cast_smul, smul_smul, rat.cast_inv, rat.cast_coe_nat,
inv_mul_cancel hn, one_smul] },
refine c.num_denom_cases_on (λ m n hn hmn, _),
rw [rat.mk_eq_div, div_eq_mul_inv, rat.cast_mul, int.cast_coe_nat, mul_smul, mul_smul,
rat.cast_coe_int, f.map_int_cast_smul, this _ n hn]
by_cases hR : (n : R) = 0; by_cases hS : (n : S) = 0,
{ simp [hR, hS] },
{ suffices : ∀ y, f y = 0, by simp [this], clear x, intro x,
rw [← inv_smul_smul₀ hS (f x), ← map_int_cast_smul f R S], simp [hR] },
{ suffices : ∀ y, f y = 0, by simp [this], clear x, intro x,
rw [← smul_inv_smul₀ hR x, map_int_cast_smul f R S, hS, zero_smul] },
{ rw [← inv_smul_smul₀ hS (f _), ← map_int_cast_smul f R S, smul_inv_smul₀ hR] }
end

lemma map_inv_nat_cast_smul {E F : Type*} [add_comm_group E] [add_comm_group F] (f : E →+ F)
(R S : Type*) [division_ring R] [division_ring S] [module R E] [module S F]
(n : ℕ) (x : E) :
f ((n⁻¹ : R) • x) = (n⁻¹ : S) • f x :=
f.map_inv_int_cast_smul R S n x

lemma map_rat_cast_smul {E F : Type*} [add_comm_group E] [add_comm_group F] (f : E →+ F)
(R S : Type*) [division_ring R] [division_ring S] [module R E] [module S F]
(c : ℚ) (x : E) :
f ((c : R) • x) = (c : S) • f x :=
by rw [rat.cast_def, rat.cast_def, div_eq_mul_inv, div_eq_mul_inv, mul_smul, mul_smul,
map_int_cast_smul f R S, map_inv_nat_cast_smul f R S]

lemma map_rat_module_smul {E : Type*} [add_comm_group E] [module ℚ E]
{F : Type*} [add_comm_group F] [module ℚ F] (f : E →+ F) (c : ℚ) (x : E) :
f (c • x) = c • f x :=
rat.cast_id c ▸ f.map_rat_cast_smul c x
rat.cast_id c ▸ f.map_rat_cast_smul ℚ ℚ c x

end add_monoid_hom

/-- There can be at most one `module ℚ E` structure on an additive commutative group. This is not
an instance because `simp` becomes very slow if we have many `subsingleton` instances,
see [gh-6025]. -/
lemma subsingleton_rat_module (E : Type*) [add_comm_group E] : subsingleton (module ℚ E) :=
⟨λ P Q, module_ext P Q $ λ r x,
@add_monoid_hom.map_rat_module_smul E ‹_› P E ‹_› Q (add_monoid_hom.id _) r x⟩

/-- If `E` is a vector space over two division rings `R` and `S`, then scalar multiplications
agree on inverses of integer numbers in `R` and `S`. -/
lemma inv_int_cast_smul_eq {E : Type*} (R S : Type*) [add_comm_group E] [division_ring R]
[division_ring S] [module R E] [module S E] (n : ℤ) (x : E) :
(n⁻¹ : R) • x = (n⁻¹ : S) • x :=
(add_monoid_hom.id E).map_inv_int_cast_smul R S n x

/-- If `E` is a vector space over two division rings `R` and `S`, then scalar multiplications
agree on inverses of natural numbers in `R` and `S`. -/
lemma inv_nat_cast_smul_eq {E : Type*} (R S : Type*) [add_comm_group E] [division_ring R]
[division_ring S] [module R E] [module S E] (n : ℕ) (x : E) :
(n⁻¹ : R) • x = (n⁻¹ : S) • x :=
(add_monoid_hom.id E).map_inv_nat_cast_smul R S n x

/-- If `E` is a vector space over two division rings `R` and `S`, then scalar multiplications
agree on rational numbers in `R` and `S`. -/
lemma rat_cast_smul_eq {E : Type*} (R S : Type*) [add_comm_group E] [division_ring R]
[division_ring S] [module R E] [module S E] (r : ℚ) (x : E) :
(r : R) • x = (r : S) • x :=
(add_monoid_hom.id E).map_rat_cast_smul R S r x

section no_zero_smul_divisors
/-! ### `no_zero_smul_divisors`
Expand Down
16 changes: 16 additions & 0 deletions src/data/rat/cast.lean
Expand Up @@ -37,6 +37,8 @@ variable [division_ring α]
-- see Note [coercion into rings]
@[priority 900] instance cast_coe : has_coe_t ℚ α := ⟨λ r, r.1 / r.2

theorem cast_def (r : ℚ) : (r : α) = r.num / r.denom := rfl

@[simp] theorem cast_of_int (n : ℤ) : (of_int n : α) = n :=
show (n / (1:ℕ) : α) = n, by rw [nat.cast_one, div_one]

Expand Down Expand Up @@ -116,6 +118,20 @@ by simp [sub_eq_add_neg, (cast_add_of_ne_zero m0 this)]
rw [(d₁.commute_cast (_:α)).inv_right₀.eq]
end

@[simp] theorem cast_inv_nat (n : ℕ) : ((n⁻¹ : ℚ) : α) = n⁻¹ :=
begin
cases n, { simp },
simp_rw [coe_nat_eq_mk, inv_def, mk, mk_nat, dif_neg n.succ_ne_zero, mk_pnat],
simp [cast_def]
end

@[simp] theorem cast_inv_int (n : ℤ) : ((n⁻¹ : ℚ) : α) = n⁻¹ :=
begin
cases n,
{ exact cast_inv_nat _ },
{ simp only [int.cast_neg_succ_of_nat, ← nat.cast_succ, cast_neg, inv_neg, cast_inv_nat] }
end

@[norm_cast] theorem cast_inv_of_ne_zero : ∀ {n : ℚ},
(n.num : α) ≠ 0 → (n.denom : α) ≠ 0 → ((n⁻¹ : ℚ) : α) = n⁻¹
| ⟨n, d, h, c⟩ := λ (n0 : (n:α) ≠ 0) (d0 : (d:α) ≠ 0), begin
Expand Down
25 changes: 9 additions & 16 deletions src/number_theory/padics/padic_numbers.lean
Expand Up @@ -812,19 +812,6 @@ begin
rw [← padic_norm_e.eq_padic_norm', ← padic.cast_eq_of_rat]
end

instance : nondiscrete_normed_field ℚ_[p] :=
{ non_trivial := ⟨padic.of_rat p (p⁻¹), begin
have h0 : p ≠ 0 := ne_of_gt (hp.1.pos),
have h1 : 1 < p := hp.1.one_lt,
rw [← padic.cast_eq_of_rat, eq_padic_norm],
simp only [padic_norm, inv_eq_zero],
simp only [if_neg] {discharger := `[exact_mod_cast h0]},
norm_cast,
simp only [padic_val_rat.inv] {discharger := `[exact_mod_cast h0]},
rw [neg_neg, padic_val_rat.padic_val_rat_self h1, gpow_one],
exact_mod_cast h1,
end⟩ }

@[simp] lemma norm_p : ∥(p : ℚ_[p])∥ = p⁻¹ :=
begin
have p₀ : p ≠ 0 := hp.1.ne_zero,
Expand All @@ -834,14 +821,20 @@ end

lemma norm_p_lt_one : ∥(p : ℚ_[p])∥ < 1 :=
begin
rw [norm_p, inv_eq_one_div, div_lt_iff, one_mul],
{ exact_mod_cast hp.1.one_lt },
{ exact_mod_cast hp.1.pos }
rw norm_p,
apply inv_lt_one,
exact_mod_cast hp.1.one_lt
end

@[simp] lemma norm_p_pow (n : ℤ) : ∥(p^n : ℚ_[p])∥ = p^-n :=
by rw [normed_field.norm_fpow, norm_p]; field_simp

instance : nondiscrete_normed_field ℚ_[p] :=
{ non_trivial := ⟨p⁻¹, begin
rw [normed_field.norm_inv, norm_p, inv_inv₀],
exact_mod_cast hp.1.one_lt
end⟩ }

protected theorem image {q : ℚ_[p]} : q ≠ 0 → ∃ n : ℤ, ∥q∥ = ↑((↑p : ℚ) ^ (-n)) :=
quotient.induction_on q $ λ f hf,
have ¬ f ≈ 0, from (padic_seq.ne_zero_iff_nequiv_zero f).1 hf,
Expand Down
2 changes: 1 addition & 1 deletion src/topology/instances/real_vector_space.lean
Expand Up @@ -26,7 +26,7 @@ suffices (λ c : ℝ, f (c • x)) = λ c : ℝ, c • f x, from _root_.congr_fu
dense_embedding_of_rat.dense.equalizer
(hf.comp $ continuous_id.smul continuous_const)
(continuous_id.smul continuous_const)
(funext $ λ r, f.map_rat_cast_smul r x)
(funext $ λ r, f.map_rat_cast_smul ℝ ℝ r x)

/-- Reinterpret a continuous additive homomorphism between two real vector spaces
as a continuous real-linear map. -/
Expand Down

0 comments on commit c400677

Please sign in to comment.