Zulip Chat Archive

Stream: new members

Topic: card


Alex Zhang (Jul 16 2021 at 10:19):

Is there any built-in lemma that picks distinct elements of a given type such as picking three as follows?

import data.fintype.card
variables {I : Type*} [fintype I] [nonempty I]
open fintype
lemma Hadamard_matrix.order_aux1 (h1 : card I  1) (h2 : card I  2) :
 i j k : I, i  j  i  k  j  k :=
sorry

My formulation might be bad btw.

Kevin Buzzard (Jul 16 2021 at 10:48):

I would first prove card >= 3 and then dig into the definition of fintype

Alex Zhang (Jul 16 2021 at 11:42):

An easier one is perhaps

import data.fintype.card
variables {I : Type*} [fintype I] [nonempty I]
open fintype
lemma ex2 (h1 : card I  1) :
 i j: I, i  j:=
begin
  have i:= classical.arbitrary I,
  use I,
 sorry,
end

Alex Zhang (Jul 16 2021 at 11:46):

A generalized one

lemma ex {n : } (h : card I  n) :
 (a : (fin n)  I),  i j, i  j  a i  a j :=
sorry

Alex Zhang (Jul 16 2021 at 11:47):

Are there any relevant or equivalent built-in lemmas to the above ones?

Shing Tak Lam (Jul 16 2021 at 11:54):

Alex Zhang said:

An easier one is perhaps

import data.fintype.card
variables {I : Type*} [fintype I] [nonempty I]
open fintype
lemma ex2 (h1 : card I  1) :
 i j: I, i  j:=
begin
  have i:= classical.arbitrary I,
  use I,
 sorry,
end

I think the case where the size isn't 1 is probably quite a bit easier than the general case

import data.fintype.card
variables {I : Type*} [fintype I] [nonempty I]
open fintype
lemma ex2 (h1 : card I  1) :
 i j: I, i  j:=
begin
  by_contra h,
  push_neg at h,
  apply h1,
  rw fintype.card,
  let i : I := classical.arbitrary I,
  have h2 : {i} = (finset.univ : finset I),
  { rw finset.eq_univ_iff_forall,
    intros x,
    rw finset.mem_singleton,
    apply h },
  simp [h2]
end

Alex Zhang (Jul 16 2021 at 11:55):

@Shing Tak Lam Do you have any idea about ex3 and ex?

Alex Zhang (Jul 16 2021 at 11:58):

I will read your proof in detail after a nap.

Eric Wieser (Jul 16 2021 at 12:38):

This is quite straightforward:

import data.fintype.card

variables {I : Type*} [fintype I]

open fintype

lemma ex1 (h1 : card I = 3) :  i j k : I, i  j  i  k  j  k :=
begin
  have f := equiv_fin_of_card_eq h1,
  refine f.symm 0, f.symm 1, f.symm 2,
    and.imp f.symm.injective.ne (and.imp f.symm.injective.ne f.symm.injective.ne) _⟩,
  sorry -- `0 ≠ 1 ∧ 0 ≠ 2 ∧ 1 ≠ 2`, all in `fin 3`
end

I don't know how to close those fin goals, but they're at least "very obviously true" rather than "handwavingly true"

Shing Tak Lam (Jul 16 2021 at 12:42):

dec_trivial works for the sorry there

Alex Zhang (Jul 16 2021 at 12:57):

equiv_fin_of_card_eq is the lemma I am looking for!!

Eric Wieser (Jul 16 2021 at 13:02):

A fin_embedding_of_lt_card would be convenient for your use case

Yakov Pechersky (Jul 16 2021 at 13:07):

docs#fin.cast_le_order_iso would help

Eric Wieser (Jul 16 2021 at 13:08):

Maybe something like this:

def trunc_fin_embedding_of_card_eq {α} [fintype α] [decidable_eq α] {n : } (h : n  fintype.card α) :
  trunc (fin n  α) :=
(trunc_equiv_fin α).map (λ e, (fin.cast_le h).to_embedding.trans e.symm.to_embedding)

def trunc_embedding_fin_of_card_le {α} [fintype α] [decidable_eq α] {n : } (h : fintype.card α  n) :
  trunc (α  fin n) :=
(trunc_equiv_fin α).map (λ e, e.to_embedding.trans (fin.cast_le h).to_embedding)

Yakov Pechersky (Jul 16 2021 at 13:10):

This is all pretty #xy. It's easier to just postulate the existence of such elements, then show the cardinality of their finset is le than the cardinality of the fintype.

Alex Zhang (Jul 19 2021 at 08:46):

Is there any version of coded lemma stating that the card of the unit group of a finite field F is exactly F.card - 1?
Also not exactly sure what the definition of "the unit group of finite field" in mathlib will be handy and is supposed to be used. Perhaps units F?

Kevin Buzzard (Jul 19 2021 at 08:47):

You should think about how you want to prove this and write down a step-by-step proof and then formalise it. My advice: stop using natural number subtraction, it just makes your life worse. Rewrite everything as addition.

Kevin Buzzard (Jul 19 2021 at 08:48):

Why not explicitly write an equiv between F and option (units F) and then deduce the addition version from results about card of option?

Johan Commelin (Jul 19 2021 at 08:49):

@Alex Zhang Did you look at src/field_theory/finite/basic.lean?

Alex Zhang (Jul 19 2021 at 08:53):

Ah, I found it! finite_field.card_units

theorem finite_field.card_units {K : Type u_1} [field K] [fintype K] :
fintype.card (units K) = fintype.card K - 1

Alex Zhang (Jul 19 2021 at 17:07):

I defined the set of quadratic residues in a finite field F, then I want to prove the card of it is half of the unit group of F, as formalised in the code.
I gave three definitions in the #mwe (not quite sure which one is the most convenient for proving this). Could anyone please point me a direction for proving this equality? The way I currently think of is to use some version of
card (im f) * card (kernel f) = card units F as f is a group hom (not sure if it is the correct or a convenient way).

import tactic
import data.fintype.card
import data.finset.basic
import field_theory.finite.basic

variables {F : Type*} [field F] [fintype F] [decidable_eq F] {p : } [char_p F p]

variable (F)

def f := λ a : F, a * a

def quad_residues : set F := (λ a, a * a) '' ((@set.univ F) \ {0})

-- alternative defns
def quad_residues' := {b //  a, a  0  a * a = b}
def quad_residues'' := {b //  (a : units F), a * a = b}

instance : fintype (quad_residues F) := sorry

example (h: p  2) : (quad_residues F).to_finset.card * 2 = fintype.card F - 1 := sorry

Yakov Pechersky (Jul 19 2021 at 17:16):

Is it possible to construct an explicit isomorphism, even if it is noncomputable?

Yakov Pechersky (Jul 19 2021 at 17:18):

You could define is_quad_residue as a Prop, and use that in a finset.filter instead.

Alex Zhang (Jul 19 2021 at 17:20):

Would this def be helpful for proving the equality?

Alex Zhang (Jul 19 2021 at 17:32):

Ah, I found the defn of "kernel". https://leanprover-community.github.io/mathlib_docs/group_theory/subgroup.html#monoid_hom.ker
and I will leave for dinner for now.

Yakov Pechersky (Jul 19 2021 at 18:33):

How about this?

import tactic
import data.fintype.card
import data.finset.basic
import field_theory.finite.basic

variables {F : Type*} [field F]

def is_quad_res (x : F) : Prop :=  (y : F), y  0  y * y = x

variables [fintype F] [decidable_eq F] {p : } [char_p F p]

open_locale classical

example (h: p  2) : ((finset.univ : finset F).filter is_quad_res).card = fintype.card F - 1 :=
begin
end

Yakov Pechersky (Jul 19 2021 at 18:34):

Is this correct?

variable (F)
def sq_hom : units F →* units F :=
λ x, x * x, by simp, λ _ _, by simp [mul_assoc, mul_comm, mul_left_comm]⟩

variable {F}
lemma sq_hom_res_iff {p : } [char_p F p]
  (x : units F) : x  (sq_hom F).ker  is_quad_res (x : F) := sorry

Alex Zhang (Jul 19 2021 at 18:57):

example (h: p ≠ 2) : ((finset.univ : finset F).filter is_quad_res).card = fintype.card F - 1 :=
should be
example (h: p ≠ 2) : ((finset.univ : finset F).filter is_quad_res).card * 2 = fintype.card F - 1 :=

Kevin Buzzard (Jul 19 2021 at 18:57):

No. The squaring function has a kernel and an image. The quadratic residues are the stuff in the image. If p>2 then the kernel is +-1 which has size 2. Hence the first isomorphism theorem says that twice the size of the image equals the size of the units (Alex' version correctly adds this factor of 2)

Kevin Buzzard (Jul 19 2021 at 18:59):

The units of a finite field are cyclic, although this is not obvious. The quadratic residues are a subgroup, so they must hence be the kernel of the map raising a unit to the power (c-1)/2 where c is the size of the field

Alex Zhang (Jul 19 2021 at 19:02):

Yes, Kevin. I am still looking for the first iso thm in mathlib. Do you have any suggestion for proving the card equality? @Kevin Buzzard

Kevin Buzzard (Jul 19 2021 at 19:04):

Yes, use the first isomorphism theorem!

Yakov Pechersky (Jul 19 2021 at 19:08):

Yes, sorry for the missing * 2 typo. Thanks Kevin for the clarification, I was going through the proof using powers of (p - 1) / 2 and realized that I must have meant image and not kernel.

Alex Zhang (Jul 19 2021 at 19:11):

I found the first iso thm: https://leanprover-community.github.io/mathlib_docs/group_theory/quotient_group.html#quotient_group.quotient_ker_equiv_range

Alex Zhang (Jul 19 2021 at 19:14):

But there are still some gaps to card.

Alex Zhang (Jul 19 2021 at 19:24):

Ah, https://leanprover-community.github.io/mathlib_docs/group_theory/coset.html#subgroup.card_eq_card_quotient_mul_card_subgroup
seems to be useful

Alex Zhang (Jul 19 2021 at 19:37):

It is weird. Why can't ring close

import tactic
import data.fintype.card
import data.finset.basic
import field_theory.finite.basic

variables {F : Type*} [field F] [fintype F] [decidable_eq F] {p : } [char_p F p]

variable (F)
def f : (units F) →* (units F) :=
λ a, a * a, by simp, (λ x y, by {ring})⟩

Yakov Pechersky (Jul 19 2021 at 19:42):

def sq_hom : units F →* units F :=
λ x, x * x, by simp, λ _ _, by simp [mul_assoc, mul_comm, mul_left_comm]⟩

Yakov Pechersky (Jul 19 2021 at 19:43):

units F is not a ring.

Yakov Pechersky (Jul 19 2021 at 19:43):

def sq_hom : units F →* units F :=
λ x, x * x, by simp, λ _ _, by simp [units.ext_iff]; ring

Yakov Pechersky (Jul 19 2021 at 20:13):

import tactic
import data.fintype.card
import data.finset.basic
import field_theory.finite.basic
import group_theory.quotient_group


variables {F : Type*} [field F]

def is_quad_res (x : F) : Prop :=  (y : F), y  0  y * y = x

lemma is_quad_res.ne_zero {x : F} (h : is_quad_res x) : x  0 :=
begin
  obtain y, hy, rfl := h,
  exact mul_ne_zero hy hy
end

variables [fintype F] [decidable_eq F] {p : } [char_p F p]

variable (F)
def sq_hom : units F →* units F :=
λ x, x * x, by simp, λ _ _, by simp [mul_assoc, mul_comm, mul_left_comm]⟩

variable {F}
lemma sq_hom_res_iff
  (x : units F) : x  (sq_hom F).range  is_quad_res (x : F) :=
begin
  simp only [sq_hom, is_quad_res, ne.def, monoid_hom.mem_range, monoid_hom.coe_mk],
  split,
  { rintro y, hy⟩,
    refine ⟨(y : F), _, _⟩,
    { simp only [units.ne_zero, not_false_iff] },
    { simp [hy] } },
  { rintro y, hn, hy⟩,
    have key : is_unit y := is_unit.mk0 y hn,
    use key.unit,
    simp [units.ext_iff, key.unit_spec, hy] }
end

example [decidable_pred (@is_quad_res F _)] (h: p  2) :
  ((finset.univ : finset F).filter is_quad_res).card * 2 = fintype.card F - 1 :=
begin
  rw finite_field.card_units,
  -- probably some neater way of constructing this, but who cares
  let iso : ((finset.univ : finset F).filter is_quad_res  (sq_hom F).range),
  { refine equiv.trans _ (equiv.subtype_equiv_right (λ x, (sq_hom_res_iff x).symm)),
    refine _, _, _, _⟩,
    { intro y,
      refine ⟨(is_unit.mk0 (y : F) (is_quad_res.ne_zero _)).unit, _⟩,
      { simpa using y.prop },
      { simpa [is_unit.unit_spec] using y.prop } },
    { rintro y,
      refine ⟨((y : units F) : F), _⟩,
      simpa using y.prop },
    { intro x,
      simp [is_unit.unit_spec] },
    { rintro x, hx⟩,
      simp [units.ext_iff, is_unit.unit_spec] } },
  have : ((finset.univ : finset F).filter is_quad_res).card = fintype.card (sq_hom F).range,
  { rw fintype.card_coe,
    convert fintype.card_congr iso },
  rw this,
  rw eq_comm,
  rw subgroup.card_eq_card_quotient_mul_card_subgroup ((sq_hom F).ker),
  congr' 1,
  { refine fintype.card_congr _,
    exact (quotient_group.quotient_ker_equiv_range _).to_equiv },
  { -- The kernel is {1, -1}, prove that elsewhere
    -- this is actually where the `(h : p ≠ 2)` hypothesis needs to be used
    sorry }
end

Alex Zhang (Jul 19 2021 at 20:24):

Cool, Yakov! I am also getting to the final part to prove that the card of the kernel is 2. Do you have any idea of proving that? @Yakov Pechersky

Kevin Buzzard (Jul 19 2021 at 20:29):

factor the quadratic?

Yakov Pechersky (Jul 19 2021 at 20:30):

Relatedly, a simpler puzzle:

lemma sq_hom_ker_eq_char_2 (h : p = 2) :
  (sq_hom F).ker =  :=
begin
  unfreezingI { subst h },
  refine le_antisymm (λ x hx, _) bot_le,
  simp only [monoid_hom.mem_ker, sq_hom, monoid_hom.coe_mk] at hx,
  simp only [subgroup.mem_bot],
  sorry
end

Alex Zhang (Jul 19 2021 at 20:33):

Thanks a lot for the proof!!

Yakov Pechersky (Jul 19 2021 at 20:51):

lemma sq_hom_ker_eq_char_2 (h : p = 2) :
  (sq_hom F).ker =  :=
begin
  unfreezingI { subst h },
  refine le_antisymm (λ x hx, _) bot_le,
  simp only [monoid_hom.mem_ker, sq_hom, monoid_hom.coe_mk, units.ext_iff, units.coe_one,
             units.coe_mul] at hx,
  rw pow_two at hx,
  haveI : fact (nat.prime 2) := nat.prime_two⟩,
  let iso : F ≃+* zmod 2,
  { refine (zmod.ring_equiv F _).symm,
    sorry
  },
  simp only [subgroup.mem_bot, units.ext_iff],
  apply iso.injective,
  have :  z, iso z = iso.to_monoid_hom z,
  { intro,
    refl },
  simp [hx, this]
end

Alex Zhang (Jul 19 2021 at 20:56):

Why is the goal at sorry fintype.card F = 2?

Kevin Buzzard (Jul 19 2021 at 20:56):

Are you claiming that every finite field of characteristic 2 has two elements? This is not true.

Kevin Buzzard (Jul 19 2021 at 20:57):

There's a field with elements 0,1,a,b with a^2=a+1=b and b^2=b+1=a. It has characteristic 2 and order 4.

Alex Zhang (Jul 19 2021 at 20:58):

Kevin Buzzard said:

Are you claiming that every finite field of characteristic 2 has two elements? This is not true.

I feel I got back to my third year (or second year) algebra course although I have got very sleepy :)

Alex Zhang (Jul 19 2021 at 21:00):

I have not set about proving card ker is 2 myself as I am too sleepy now.

Yakov Pechersky (Jul 19 2021 at 21:00):

I see, apologies for the wrong statement! I have never actually taken algebra at that level, and have been trying to learn it myself.

Alex Zhang (Jul 19 2021 at 21:01):

You have already given many helpful answers, Yakov. Many thanks! @Yakov Pechersky

Yakov Pechersky (Jul 19 2021 at 21:02):

I was not sure how to get Fermat's Little Theorem to work on arbitrary finite fields, but we have it for zmod p. So I faked it =/

Kevin Buzzard (Jul 19 2021 at 21:02):

Just like you can make the complexes by starting with the reals and throwing in a root of a real quadratic which doesn't have a real root, you can do the same with the field with two elements, throwing in a root of X^2=X+1. This polynomial mod 2 doesn't have 0 or 1 as a root, so throw a root in and you get something 2-dimensional over {0,1}.

Kevin Buzzard (Jul 19 2021 at 21:03):

Fermat's little theorem follows from the theorem in group theory that the order of the element divides the order of the group, applied to the unit group. This does not need the deeper fact that this group is cyclic

Yakov Pechersky (Jul 19 2021 at 21:04):

Ah, of course! I was just formalizing notes from Gross's class about this.

Alex Zhang (Jul 20 2021 at 11:58):

I have proved the card of the ker is 2, but have not sorted things out.

Yakov Pechersky (Jul 20 2021 at 12:58):

Did you prove it by explicitly showing that the ker is 1 and -1 for the appropriate p?

Alex Zhang (Jul 20 2021 at 13:33):

Yes, doing something like

lemma f_0 : (f F).ker.carrier = {1, -1} :=
begin
  rw ker,
  simp [f_ker, subgroup.comap, set.preimage, f],
  ext,
  simp,
  split,
  any_goals {intro h},
  { rw units.ext_iff at h,
    simp at h,
    have h' : ((x : F) + 1) * (x - 1) = 0,
    {simp [add_mul, mul_sub, h], ring},
    simp at h',
    cases h',
    {right, simp [units.ext_iff, eq_neg_of_add_eq_zero h'],},
    {left, simp [units.ext_iff, sub_eq_zero.mp h']}
  },
  cases h; simp [h]
end

Yakov Pechersky (Jul 20 2021 at 14:21):

Golfed:

lemma sq_hom_ker_eq : (sq_hom F).ker.carrier = {1, -1} :=
begin
  ext x,
  simp only [monoid_hom.mem_ker, set.mem_insert_iff, subgroup.mem_carrier, set.mem_singleton_iff,
             sq_hom, monoid_hom.coe_mk, units.ext_iff, units.coe_mul, units.coe_one, units.coe_neg],
  refine λ h, _, λ h, _⟩,
  { have h' : ((x : F) + 1) * (x - 1) = 0,
    { rw [add_mul, mul_sub, h], ring },
    rw mul_eq_zero at h',
    exact h'.symm.imp eq_of_sub_eq_zero eq_neg_of_add_eq_zero },
  { cases h;
    simp [h] }
end

Damiano Testa (Jul 20 2021 at 15:03):

Is there a way to recycle mul_self_eq_one_iff more efficiently? I feel that the proof of units.sq_one should be much shorter...

lemma monoid_hom.ker_mul_self {x : units F} : x  monoid_hom.ker (sq_hom F)  x * x = 1 := iff.rfl

lemma units.sq_one {F : Type*} [integral_domain F] {x : units F} :
  x * x = 1  x = 1  x = - 1 :=
begin
  convert @mul_self_eq_one_iff F _ x using 1; refine eq_iff_iff.mpr _,
  { exact congr_arg coe, λ h, units.eq_iff.mp h },
  { refine _, _; rintros (h | h),
    { exact or.inl (by simp [h]) },
    { exact or.inr (by simp [h]) },
    { exact or.inl (by simpa using h) },
    { exact or.inr (units.ext (by simpa using h)) } },
end

lemma f_0 : (sq_hom F).ker.carrier = {1, -1} :=
by ext; simp [monoid_hom.ker_mul_self, units.sq_one]

Damiano Testa (Jul 21 2021 at 07:52):

Also, note that it might make sense to develop some API for the slightly more general version of sq_hom below.

def mul_self_hom (F : Type*) [comm_monoid F] : F →* F :=
λ x, x * x, mul_one _, λ _ _, mul_mul_mul_comm _ _ _ _

Your version, would be the above applied to units F.

Possibly, even for the more general nat-power map

def pow_self_hom (F : Type*) [comm_monoid F] (n : ) : F →* F :=
λ x, x ^ n, one_pow _, λ _ _, mul_pow _ _ _

Kevin Buzzard (Jul 21 2021 at 08:04):

IIRC this map is already in mathlib

Kevin Buzzard (Jul 21 2021 at 08:04):

Or perhaps there's an old skool is_monoid_hom instance on the power map

Damiano Testa (Jul 21 2021 at 08:05):

Ah, in either case, it might make sense to generalize some of the lemmas above to work for this more general setting.


Last updated: Dec 20 2023 at 11:08 UTC