Zulip Chat Archive
Stream: mathlib4
Topic: Fintype (Group G)
Yakov Pechersky (Jun 04 2023 at 20:25):
I couldn't find an instance that we have a finite number of groups over a finite type. I tried using the recently ported/rewritten %derive_fintype
to magically generate the instances for Fintypes, but ran into issues over npow
and zpow
. Is there a way to get the deriver to work for such structures with autoParam functions? I've provided a proof that npowRec
is the unique inhabitant of the relevant subtype:
import Mathlib.Tactic.DeriveFintype
import Mathlib.Data.Fintype.Pi
instance {G : Type _} [Fintype G] [DecidableEq G] : Fintype (One G) := derive_fintype% _
instance {G : Type _} [Fintype G] [DecidableEq G] : Fintype (Mul G) := derive_fintype% _
instance {G : Type _} [Fintype G] [DecidableEq G] : Fintype (Semigroup G) := derive_fintype% _
lemma np_inj {G : Type _} [Semigroup G] [One G]
(np np' : ℕ → G → G) (nph0 : ∀ x, np 0 x = 1) (nph0' : ∀ x, np' 0 x = 1)
(nph1 : ∀ n x, np (n + 1) x = x * np n x)
(nph1' : ∀ n x, np' (n + 1) x = x * np' n x) : np = np' := by
ext n x
induction' n with n IH generalizing x <;>
simp_all
instance np_unique {G : Type _} [Semigroup G] [One G] :
Unique {np : ℕ → G → G // (∀ x, np 0 x = 1) ∧ (∀ n x, np (n + 1) x = x * np n x)} :=
⟨⟨npowRec, by intros; rfl, by intros; rfl⟩,
λ f => (Subtype.ext
(np_inj _ _ f.prop.left (by intros; rfl) f.prop.right (by intros; rfl)))⟩
instance np_fintype {G : Type _} [Semigroup G] [One G] :
Fintype {np : ℕ → G → G // (∀ x, np 0 x = 1) ∧ (∀ n x, np (n + 1) x = x * np n x)} :=
np_unique.fintype
instance {G : Type _} [Fintype G] [DecidableEq G] : Fintype (Monoid G) := derive_fintype% _ -- fails,
-- probably because can't show that there are finite `npow`
instance {G : Type _} [Fintype G] [DecidableEq G] : Fintype (Div G) := derive_fintype% _
instance {G : Type _} [Fintype G] [DecidableEq G] : Fintype (Inv G) := derive_fintype% _
instance {G : Type _} [Fintype G] [DecidableEq G] : Fintype (DivInvMonoid G) := derive_fintype% _ -- fails,
-- probably because can't show that there are finite `zpow`
instance {G : Type _} [Fintype G] [DecidableEq G] : Fintype (Group G) := derive_fintype% _
Yury G. Kudryashov (Jun 04 2023 at 23:51):
Do we have an ext
lemma from Group
to Mul
?
Yury G. Kudryashov (Jun 04 2023 at 23:51):
I know nothing about derive_fintype%
. As for Finite (Group G)
, you can easily get it from an injective map to G -> G -> G
.
Yury G. Kudryashov (Jun 04 2023 at 23:52):
Some time ago, I started (then abandoned) a branch where I merged npow
and rules into 1 structure.
Yury G. Kudryashov (Jun 04 2023 at 23:52):
This structure is a Subsingleton
.
Eric Wieser (Jun 05 2023 at 00:03):
Yury G. Kudryashov said:
Do we have an
ext
lemma fromGroup
toMul
?
Kyle Miller (Jun 05 2023 at 00:48):
derive_fintype% t
is short for Fintype.ofEquiv _ (proxy_equiv% t)
, and you can see what equivalence it is generating with
#check fun G => proxy_equiv% (Monoid G)
/-
fun G ↦
Monoid.proxyTypeEquiv
G : (G : Type u_1) →
(toSemigroup : Semigroup G) ×
(toOne : One G) ×
(_ : PLift (∀ (a : G), 1 * a = a)) ×
(_ : PLift (∀ (a : G), a * 1 = a)) ×
(npow : ℕ → G → G) ×
(_ : PLift (autoParam (∀ (x : G), npow 0 x = 1) _auto✝)) ×
PLift (autoParam (∀ (n : ℕ) (x : G), npow (n + 1) x = x * npow n x) _auto✝¹) ≃
Monoid G
-/
It's just relying on whatever instances Mathlib has to create a Fintype
instance, and there aren't any instances that can see that the ℕ → G → G
is determined by the following two fields.
Potentially the proxy_equiv%
elaborator could be made aware of which fields are functions of the others due to Prop fields and omit them. I don't think being aware of autoParam
is sufficient though since you also need the Subsingleton
proof that Yury mentioned.
Yakov Pechersky (Jun 05 2023 at 01:01):
Here is the full proof up to Fintype (Group)
, where I do provide the Unique
, and thus Fintype
, instances.
import Mathlib.Tactic.DeriveFintype
import Mathlib.Data.Fintype.Pi
instance {G : Type _} [Fintype G] [DecidableEq G] : Fintype (One G) := derive_fintype% _
instance {G : Type _} [Fintype G] [DecidableEq G] : Fintype (Mul G) := derive_fintype% _
instance {G : Type _} [Fintype G] [DecidableEq G] : Fintype (Semigroup G) := derive_fintype% _
lemma np_inj {G : Type _} [Mul G] [One G]
(np np' : ℕ → G → G) (nph0 : ∀ x, np 0 x = 1) (nph0' : ∀ x, np' 0 x = 1)
(nph1 : ∀ n x, np (n + 1) x = x * np n x)
(nph1' : ∀ n x, np' (n + 1) x = x * np' n x) : np = np' := by
ext n x
induction' n with n IH generalizing x <;>
simp_all
instance np_unique {G : Type _} [Mul G] [One G] :
Unique {np : ℕ → G → G // (∀ x, np 0 x = 1) ∧ (∀ n x, np (n + 1) x = x * np n x)} :=
⟨⟨npowRec, by intros; rfl, by intros; rfl⟩,
λ f => (Subtype.ext
(np_inj _ _ f.prop.left (by intros; rfl) f.prop.right (by intros; rfl)))⟩
instance np_fintype {G : Type _} [Mul G] [One G] :
Fintype {np : ℕ → G → G // (∀ x, np 0 x = 1) ∧ (∀ n x, np (n + 1) x = x * np n x)} :=
np_unique.fintype
instance {G : Type _} [Semigroup G] [One G] : Fintype (@Sigma (ℕ → G → G) fun npow ↦
(_ : PLift ((∀ (x : G), npow 0 x = 1))) ×
PLift ((∀ (n : ℕ) (x : G), npow (n + 1) x = x * npow n x))) :=
Fintype.ofEquiv {np : ℕ → G → G // (∀ x, np 0 x = 1) ∧ (∀ n x, np (n + 1) x = x * np n x)} {
toFun := λ ⟨f, hf⟩ => ⟨f, PLift.up hf.left, PLift.up hf.right⟩
invFun := λ ⟨f, hf⟩ => ⟨f, hf.fst.down, hf.snd.down⟩
left_inv := λ ⟨f, hf⟩ => by simp
right_inv := λ ⟨f, hf⟩ => by simp
}
instance {G : Type _} [Fintype G] [DecidableEq G] : Fintype (Monoid G) := derive_fintype% _
instance {G : Type _} [Fintype G] [DecidableEq G] : Fintype (Div G) := derive_fintype% _
instance {G : Type _} [Fintype G] [DecidableEq G] : Fintype (Inv G) := derive_fintype% _
lemma zp_inj {G : Type _} [Mul G] [One G] [Inv G]
(zp zp' : ℤ → G → G) (zph0 : ∀ x, zp 0 x = 1) (zph0' : ∀ x, zp' 0 x = 1)
(zph1 : ∀ (n : ℕ) (a : G), zp (Int.ofNat (Nat.succ n)) a = a * zp (Int.ofNat n) a)
(zph1' : ∀ (n : ℕ) (a : G), zp' (Int.ofNat (Nat.succ n)) a = a * zp' (Int.ofNat n) a)
(zphn : ∀ (n : ℕ) (a : G), zp (Int.negSucc n) a = (zp (Int.ofNat (Nat.succ n)) a)⁻¹)
(zphn' : ∀ (n : ℕ) (a : G), zp' (Int.negSucc n) a = (zp' (Int.ofNat (Nat.succ n)) a)⁻¹) :
zp = zp'
:= by
ext n x
induction' n with n n generalizing x
· induction n
· simp_all
· simp_all
· rw [zphn, zphn', zph1, zph1']
congr
induction n
· simp_all
· simp_all
instance zp_unique {G : Type _} [Mul G] [One G] [Inv G] :
Unique {zp : ℤ → G → G // (∀ x, zp 0 x = 1) ∧
(∀ (n : ℕ) (a : G), zp (Int.ofNat (Nat.succ n)) a = a * zp (Int.ofNat n) a) ∧
(∀ (n : ℕ) (a : G), zp (Int.negSucc n) a = (zp (Int.ofNat (Nat.succ n)) a)⁻¹)} :=
⟨⟨zpowRec, by intros; rfl, by intros; rfl, by intros; rfl⟩,
λ f => (Subtype.ext (zp_inj _ _ f.prop.left (by intros; rfl) f.prop.right.left (by intros; rfl)
f.prop.right.right (by intros; rfl)))⟩
instance zp_fintype {G : Type _} [Mul G] [One G] [Inv G]:
Fintype {zp : ℤ → G → G // (∀ x, zp 0 x = 1) ∧
(∀ (n : ℕ) (a : G), zp (Int.ofNat (Nat.succ n)) a = a * zp (Int.ofNat n) a) ∧
(∀ (n : ℕ) (a : G), zp (Int.negSucc n) a = (zp (Int.ofNat (Nat.succ n)) a)⁻¹)} :=
zp_unique.fintype
instance {G : Type _} [Mul G] [One G] [Inv G] : Fintype (@Sigma (ℤ → G → G) fun zpow ↦
(_ : PLift ((∀ (a : G), zpow 0 a = 1))) ×
(_ : PLift ((∀ (n : ℕ) (a : G), zpow (Int.ofNat (Nat.succ n)) a = a * zpow (Int.ofNat n) a))) ×
PLift ((∀ (n : ℕ) (a : G), zpow (Int.negSucc n) a = (zpow (↑(Nat.succ n)) a)⁻¹))) :=
Fintype.ofEquiv {zp : ℤ → G → G // (∀ x, zp 0 x = 1) ∧
(∀ (n : ℕ) (a : G), zp (Int.ofNat (Nat.succ n)) a = a * zp (Int.ofNat n) a) ∧
(∀ (n : ℕ) (a : G), zp (Int.negSucc n) a = (zp (Int.ofNat (Nat.succ n)) a)⁻¹)} {
toFun := λ ⟨f, hf⟩ => ⟨f, PLift.up hf.left, PLift.up hf.right.left, PLift.up hf.right.right⟩
invFun := λ ⟨f, hf⟩ => ⟨f, hf.fst.down, hf.snd.fst.down, hf.snd.snd.down⟩
left_inv := λ ⟨f, hf⟩ => by simp
right_inv := λ ⟨f, hf, hf', hf''⟩ => by simp
}
instance {G : Type _} [Fintype G] [DecidableEq G] : Fintype (DivInvMonoid G) := derive_fintype% _
instance {G : Type _} [Fintype G] [DecidableEq G] : Fintype (Group G) := derive_fintype% _
Yakov Pechersky (Jun 05 2023 at 01:03):
And, nicely, one can now "brute force":
lemma foo : Fintype.card (Group Unit) = 1 := by decide
Yakov Pechersky (Jun 05 2023 at 01:04):
But unfortunately, it slows to a half for me, for
lemma foo2 : Fintype.card (Group Bool) = 2 := by decide
failing with a deterministic timeout
Eric Wieser (Jun 05 2023 at 01:07):
I would hope there's a way of doing this that doesn't require repeating the proofs about npow in Monoid.ext
Eric Wieser (Jun 05 2023 at 01:10):
Something like considering the subtype
{ omi : G × (G → G → G) × (G → G) // ∃ h1 h2 ..., Group.mk ... }
≃ Group G
Kevin Buzzard (Jun 05 2023 at 08:44):
You only need the multiplication!
Eric Wieser (Jun 05 2023 at 08:47):
Not if you want to be constructive!
Eric Wieser (Jun 05 2023 at 08:49):
(sure, you can find inv and one constructively by iteration; but it's easier to just declare all three and let the fintype machinery iterate)
Kevin Buzzard (Jun 05 2023 at 08:50):
If I'm actually counting the number of group structures on a type of size n then surely it's easier to just loop over the multiplications the moment n>=2?
Eric Wieser (Jun 05 2023 at 08:53):
If you only want to count them, yes; but Fintype (Group G)
asks you to construct each one too
Eric Wieser (Jun 05 2023 at 08:56):
Also, it's not clear to me how you check the multiplication forms a group without identifying the inverse and identity along the way
Johan Commelin (Jun 05 2023 at 08:59):
Wasn't there some weird 1-axiom characterisation of groups?
Eric Wieser (Jun 05 2023 at 09:07):
Yes, but none are in terms of solely multiplication
Last updated: Dec 20 2023 at 11:08 UTC