Zulip Chat Archive

Stream: mathlib4

Topic: Finiteness of a `Set (ℕ × ℕ × ℕ)` with bounded components


Jeremy Tan (Aug 12 2023 at 16:23):

What's the shortest way to prove that a Set of tuples of natural numbers is finite, given that all components of tuples in the set are bounded?

import Mathlib.Data.Finset.Basic
import Mathlib.Data.Fintype.CardEmbedding
import Mathlib.Data.Nat.Prime
import Mathlib.Tactic.Linarith

section Defs

variable (k : ) [hk : Fact (4 * k + 1).Prime]

def zagierSet := {t :  ×  ×  | t.1 * t.1 + 4 * t.2.1 * t.2.2 = 4 * k + 1}

theorem zagierSet_lower_bound (h : (x, y, z)  zagierSet k) : 0 < x  0 < y  0 < z := by
  simp_rw [zagierSet, Set.mem_setOf_eq] at h
  refine' _, _, _ <;> (by_contra q; push_neg at q; rw [le_zero_iff] at q; subst q; simp at h)
  · apply_fun (· % 4) at h
    simp [mul_assoc, Nat.add_mod] at h
  all_goals cases' (Nat.dvd_prime hk.out).1 (dvd_of_mul_left_eq _ h) with e e <;>
    (subst e; simp at h; subst h; simp at hk; exact hk.out)

theorem zagierSet_upper_bound (h : (x, y, z)  zagierSet k) : x  k + 1  y  k  z  k := by
  obtain hx, hy, hz := zagierSet_lower_bound k h
  simp_rw [zagierSet, Set.mem_setOf_eq] at h
  refine' _, _, _ <;> nlinarith

instance fintypeZagierSet : Fintype (zagierSet k) := by
  sorry

end Defs

Adam Topaz (Aug 12 2023 at 16:27):

You can embed it into a type that’s known to be finite and use Fintype.ofInjcetive.

Adam Topaz (Aug 12 2023 at 16:27):

docs#Fintype.ofInjective

Anatole Dedecker (Aug 12 2023 at 16:29):

It's probably easier to stay with docs#Set.Finite for the proof (e.g you have docs#Set.Finite.subset) and then use docs#Set.Finite.fintype

Adam Topaz (Aug 12 2023 at 16:30):

With the proven bounds, it should be easy to embed it in Fin (k+2) x Fin (k+1) x Fin (k+ 1)

Jeremy Tan (Aug 12 2023 at 16:30):

(The context is Zagier's "one-sentence proof" of the sum of two squares theorem, from Wikipedia, using cardinalities of involutions)

Jeremy Tan (Aug 12 2023 at 16:34):

Anatole Dedecker said:

It's probably easier to stay with docs#Set.Finite for the proof (e.g you have docs#Set.Finite.subset) and then use docs#Set.Finite.fintype

like this?

instance finiteZagierSet : (zagierSet k).Finite := by
  sorry

Alex J. Best (Aug 12 2023 at 16:35):

Jeremy Tan said:

(The context is Zagier's "one-sentence proof" of the sum of two squares theorem, from Wikipedia, using cardinalities of involutions)

I also tried this long ago in lean 3, hopefully it is much easier now with the development of mathlib. At the time I remember finiteness statements like this being a nightmare

Alex J. Best (Aug 12 2023 at 16:36):

Jeremy Tan said:

Anatole Dedecker said:

It's probably easier to stay with docs#Set.Finite for the proof (e.g you have docs#Set.Finite.subset) and then use docs#Set.Finite.fintype

like this?

instance fintypeZagierSet : Set.Finite (zagierSet k) := by
  sorry

Set.Finite isn't a typeclass, so this should just be a lemma

Jeremy Tan (Aug 12 2023 at 16:36):

oeps

Jeremy Tan (Aug 12 2023 at 16:53):

Adam Topaz said:

With the proven bounds, it should be easy to embed it in Fin (k+2) x Fin (k+1) x Fin (k+ 1)

Fin (k + 2) × Fin (k + 1) × Fin (k + 1) isn't a set…

Adam Topaz (Aug 12 2023 at 16:56):

Yes, your original message asked for a fintype instance…

Jeremy Tan (Aug 12 2023 at 16:56):

This doesn't work

theorem finiteZagierSet : (zagierSet k).Finite := by
  refine' @Set.Finite.subset (Fin (k + 2) × Fin (k + 1) × Fin (k + 1)) Set.univ inferInstance _ _

Adam Topaz (Aug 12 2023 at 16:59):

What I was suggesting is to define an injective map from the type associated to your set into this product of Fins, then use the lemma I mentioned to prove that the type associated to your set is a fintype. If you want a proof using Set.Finite then this approach might not be the best.

Adam Topaz (Aug 12 2023 at 17:00):

Unfortunately I’m away from my computer for the rest of the day, so I can’t help much with actual lean code

Jeremy Tan (Aug 12 2023 at 17:06):

I think I got the right statement

instance zagierSetEmbedding : {t // t  zagierSet k}  Fin (k + 2) × Fin (k + 1) × Fin (k + 1) := by
  sorry

Adam Topaz (Aug 12 2023 at 17:08):

That shouldn’t be an instance

Adam Topaz (Aug 12 2023 at 17:08):

And you don’t necessarily need subtype notation

Eric Wieser (Aug 12 2023 at 17:08):

I think you might have an easier time showing that it's equal to (Finset.Ioc 0 (k + 1)).product <| (Finset.Ioc 0 k)).product <| Finset.Ioc 0 k) filtered by the obvious relation

Adam Topaz (Aug 12 2023 at 17:09):

Maybe contained in, as opposed to equal to?

Adam Topaz (Aug 12 2023 at 17:10):

That way you don’t need any relation, and should still suffice for Set.Finite

Adam Topaz (Aug 12 2023 at 17:11):

Also, probably docs#Finset.Icc ?

Jeremy Tan (Aug 12 2023 at 17:15):

Eric Wieser said:

I think you might have an easier time showing that it's equal to (Finset.Ioc 0 (k + 1)).product <| (Finset.Ioc 0 k)).product <| Finset.Ioc 0 k) filtered by the obvious relation

failed to synthesize instance
  LocallyFiniteOrder 

Johan Commelin (Aug 12 2023 at 17:15):

I hope that only means you are missing an import

Jeremy Tan (Aug 12 2023 at 17:16):

yeah, the required instance is in Data.Nat.Interval

Jeremy Tan (Aug 12 2023 at 17:25):

Seems a bit better now

import Mathlib.Data.Nat.Interval
import Mathlib.Data.Nat.Prime
import Mathlib.Tactic.Linarith

section Defs

open Finset

variable (k : ) [hk : Fact (4 * k + 1).Prime]

def zagierSet := {t :  ×  ×  | t.1 * t.1 + 4 * t.2.1 * t.2.2 = 4 * k + 1}

lemma zagierSet_lower_bound (h : (x, y, z)  zagierSet k) : 0 < x  0 < y  0 < z := by
  simp_rw [zagierSet, Set.mem_setOf_eq] at h
  refine' _, _, _ <;> (by_contra q; push_neg at q; rw [le_zero_iff] at q; subst q; simp at h)
  · apply_fun (· % 4) at h
    simp [mul_assoc, Nat.add_mod] at h
  all_goals cases' (Nat.dvd_prime hk.out).1 (dvd_of_mul_left_eq _ h) with e e <;>
    (subst e; simp at h; subst h; simp at hk; exact hk.out)

lemma zagierSet_upper_bound (h : (x, y, z)  zagierSet k) : x  k + 1  y  k  z  k := by
  obtain hx, hy, hz := zagierSet_lower_bound k h
  simp_rw [zagierSet, Set.mem_setOf_eq] at h
  refine' _, _, _ <;> nlinarith

def zagierFinset :=
  ((Ioc 0 (k + 1)).product ((Ioc 0 k).product (Ioc 0 k))).filter
    (fun x, y, z => x * x + 4 * y * z = 4 * k + 1)

def zagierSetEquiv : zagierSet k  zagierFinset k where
  toFun := fun ⟨⟨x, y, z⟩, h => by
    obtain hx, hy, hz := zagierSet_upper_bound k h
    exact ⟨(x, y, z), by simp
    sorry

end Defs

Eric Wieser (Aug 12 2023 at 17:31):

You should be showing zagierSet k = zagierFinset k!

Jeremy Tan (Aug 12 2023 at 17:32):

It's 1:30am here...

Jeremy Tan (Aug 12 2023 at 17:33):

I should be sleeping but the thrill is preventing me from doing that

Jeremy Tan (Aug 12 2023 at 17:37):

(deleted)

Jeremy Tan (Aug 12 2023 at 17:44):

What's the correct theorem to show that two sets are equal by showing that every element of one set is contained in the other?

Jeremy Tan (Aug 12 2023 at 17:45):

A documentation search doesn't turn up anything

Jeremy Tan (Aug 12 2023 at 17:45):

oh, wait, ext might do it

Jeremy Tan (Aug 12 2023 at 18:02):

whee

theorem zagierSet_eq : zagierSet k = zagierFinset k := by
  ext x, y, z
  refine' fun h => _, fun h => _
  · unfold zagierSet at h
    unfold zagierFinset; simp_all
    have lb := zagierSet_lower_bound k h
    have ub := zagierSet_upper_bound k h
    apply mem_product.2; simp
    constructor; · exact lb.1, ub.1
    apply mem_product.2; simp
    exact ⟨⟨lb.2.1, ub.2.1⟩, lb.2.2, ub.2.2⟩⟩
  · unfold zagierFinset at h
    unfold zagierSet; simp_all

Eric Wieser (Aug 12 2023 at 18:49):

(zagierSet k).Finite should follow trivially from there, though you probably don't need it at all now you have the finset

Yaël Dillies (Aug 12 2023 at 21:21):

Eric Wieser said:

I think you might have an easier time showing that it's equal to (Finset.Ioc 0 (k + 1)).product <| (Finset.Ioc 0 k)).product <| Finset.Ioc 0 k) filtered by the obvious relation

/me screams in unused notation

Eric Wieser (Aug 12 2023 at 21:21):

I never set up a global input method and didn't have lean open. Indeed, using notation for docs#Finset.product would be better

Jeremy Tan (Aug 13 2023 at 06:16):

This is the key theorem used in Zagier's proof – not sure how to go from here

import Mathlib.Dynamics.PeriodicPts
import Mathlib.Data.Fintype.Card
import Mathlib.Data.Nat.ModEq

variable [Fintype α] [DecidableEq α] {p : } [Fact p.Prime]

open Function

theorem card_fixedPoints_modEq_card (f : α  α) (hf : f^[p] = id) :
    Fintype.card (fixedPoints f)  Fintype.card α [MOD p] := by
  sorry

Jeremy Tan (Aug 13 2023 at 06:48):

There needs to be some statement that "α decomposes into its orbits under f" but no idea where that is

Jeremy Tan (Aug 13 2023 at 07:05):

The orbit-stabiliser theorem may help, but how do I put a group structure on the function application?

Eric Wieser (Aug 13 2023 at 08:24):

docs#Function.End

Alex J. Best (Aug 13 2023 at 17:42):

Probably the quickest way in mathlib is to use the fact that the submonoid generated by your fixed morphism is finite, hence actually a group

Alex J. Best (Aug 13 2023 at 17:44):

Searching the docs I found https://leanprover-community.github.io/mathlib4_docs/Mathlib/GroupTheory/PGroup.html#IsPGroup.card_modEq_card_fixedPoints

Jeremy Tan (Aug 15 2023 at 06:17):

OK, I'm really confused now

import Mathlib.Dynamics.PeriodicPts
import Mathlib.Data.Fintype.Card
import Mathlib.Data.Nat.ModEq
import Mathlib.GroupTheory.GroupAction.Quotient
import Mathlib.GroupTheory.PGroup
import Mathlib.GroupTheory.Submonoid.Membership

variable {α : Type*} [Fintype α] [DecidableEq α] {p : } [Fact p.Prime]
  (f : α  α) (hf : f^[p] = id)

open Function Submonoid

def iterClosure : Submonoid (Function.End α) := powers f

def groupIterClosure : Group (iterClosure f) where
  inv g := f^[p - 1], by
    unfold iterClosure
    rw [mem_powers_iff]
    use p - 1
    sorry
  mul_left_inv k := sorry

I don't know how to get from HPow to Nat.iterate in the first sorry

α: Type u_1
inst✝²: Fintype α
inst✝¹: DecidableEq α
p: 
inst: Fact (Nat.Prime p)
f: α  α
hf: f^[p] = id
g: { x // x  iterClosure f }
 f ^ (p - 1) = f^[p - 1]

Jeremy Tan (Aug 15 2023 at 06:19):

MonoidHom.coe_pow doesn't work because it expects Monoid.End rather than the type of f, which is Function.End

Damiano Testa (Aug 15 2023 at 06:44):

I do not really know the End-part of mathlib, but maybe there is a missing lemma:

theorem missing? (f : Function.End α) (k : ) : f ^ k = f^[k] := by
  induction k with
    | zero => rfl
    | succ n ih =>
      simp only [iterate_succ',  ih, pow_succ]
      rfl

def groupIterClosure : Group (iterClosure f) where
  inv g := f^[p - 1], by
    unfold iterClosure
    rw [mem_powers_iff]
    use p - 1
    apply missing?
  mul_left_inv k := sorry

Yaël Dillies (Aug 15 2023 at 07:07):

Note that I have a PR making missing? true definitionally.

Damiano Testa (Aug 15 2023 at 07:16):

It seems that missing API in Lean is a synonym for "Yaël has a PR for it".

Yaël Dillies (Aug 15 2023 at 08:06):

... or Eric!

Jeremy Tan (Aug 15 2023 at 09:11):

Yaël Dillies said:

Note that I have a PR making missing? true definitionally.

Yes. Where is it?

Jeremy Tan (Aug 15 2023 at 09:16):

Is it #862?!

Eric Wieser (Aug 15 2023 at 09:25):

I'd argue we're missing some API for type-casting with Function.End and Monoid.End, which is why missing? is missing

Jeremy Tan (Aug 15 2023 at 09:56):

I don't know how to deal with the build failures in #862

Jeremy Tan (Aug 15 2023 at 09:56):

The failures in Algebra.Group.Units mention rfl but rfl is nowhere to be found

Eric Wieser (Aug 15 2023 at 11:54):

the rfl is in the default value for a field you didn't provide

Jeremy Tan (Aug 15 2023 at 14:04):

Now Lean simply refuses to rewrite the * in the goal state before the sorry (g^[p - 1] * g = 1) to function composition

import Mathlib.Dynamics.PeriodicPts
import Mathlib.Data.Fintype.Card
import Mathlib.Data.Nat.ModEq
import Mathlib.GroupTheory.GroupAction.Quotient
import Mathlib.GroupTheory.PGroup
import Mathlib.GroupTheory.Submonoid.Membership

variable {α : Type*} [Fintype α] [DecidableEq α] {p : } [Fact p.Prime]
  (f : Function.End α) (hf : f^[p] = id)

open Function Submonoid

theorem pow_eq_iterate (k : ) : f ^ k = f^[k] := by
  induction k with
    | zero => rfl
    | succ n ih =>
      simp only [iterate_succ',  ih, pow_succ]
      rfl

def iterClosure : Submonoid (Function.End α) := powers f

def groupIterClosure : Group (iterClosure f) where
  inv := fun g, hg => g^[p - 1], by
    unfold iterClosure at hg 
    rw [mem_powers_iff] at hg 
    obtain k, hk := hg
    use k * (p - 1)
    rw [ pow_eq_iterate,  hk, pow_mul]⟩
  mul_left_inv := fun g, hg => by
    simp only [ge_iff_le, mk_mul_mk]
    congr
    sorry

Jeremy Tan (Aug 15 2023 at 14:08):

wait…

Jeremy Tan (Aug 15 2023 at 14:13):

yeah this works

import Mathlib.Dynamics.PeriodicPts
import Mathlib.Data.Fintype.Card
import Mathlib.Data.Nat.ModEq
import Mathlib.GroupTheory.GroupAction.Quotient
import Mathlib.GroupTheory.PGroup
import Mathlib.GroupTheory.Submonoid.Membership

variable {α : Type*} [Fintype α] [DecidableEq α] {p : } [hp : Fact p.Prime]
  (f : Function.End α) (hf : f^[p] = id)

open Function Submonoid

theorem pow_eq_iterate (k : ) : f ^ k = f^[k] := by
  induction k with
    | zero => rfl
    | succ n ih =>
      simp only [iterate_succ',  ih, pow_succ]
      rfl

def groupIterClosure : Group (powers f) where
  inv := fun g, hg => g^[p - 1], by
    rw [mem_powers_iff] at hg 
    obtain k, hk := hg
    use k * (p - 1)
    rw [ pow_eq_iterate,  hk, pow_mul]⟩
  mul_left_inv := fun g, hg => by
    simp only [ge_iff_le, mk_mul_mk]
    congr
    rw [ pow_eq_iterate,  pow_succ',
      Nat.sub_add_cancel (one_le_two.trans (Nat.Prime.two_le hp.out))]
    rw [mem_powers_iff] at hg
    obtain k, hk := hg
    rw [ hk,  pow_mul, mul_comm, pow_mul, pow_eq_iterate f, hf, pow_eq_iterate, iterate_id]
    rfl

Jeremy Tan (Aug 15 2023 at 14:13):

(hp being the Fact that p is prime)

Jeremy Tan (Aug 15 2023 at 15:09):

This is much better, but how can I prove the last instance below (with the sorry)?

import Mathlib.GroupTheory.PGroup

section Key

variable {α : Type*} [Fintype α] [DecidableEq α] {p : } [hp : Fact p.Prime]
  (f : Function.End α) (hf : f^[p] = id)

open Function Submonoid

/-- A shim theorem. -/
theorem pow_eq_iterate (k : ) : f ^ k = f^[k] := by
  induction k with
    | zero => rfl
    | succ n ih =>
      simp only [iterate_succ',  ih, pow_succ]
      rfl

def groupPowers : Group (powers f) where
  inv := fun g, hg => g^[p - 1], by
    rw [mem_powers_iff] at hg 
    obtain k, hk := hg
    use k * (p - 1)
    rw [ pow_eq_iterate,  hk, pow_mul]⟩
  mul_left_inv := fun g, hg => by
    simp only [ge_iff_le, mk_mul_mk]
    congr
    rw [ pow_eq_iterate,  pow_succ',
      Nat.sub_add_cancel (one_le_two.trans (Nat.Prime.two_le hp.out))]
    rw [mem_powers_iff] at hg
    obtain k, hk := hg
    rw [ hk,  pow_mul, mul_comm, pow_mul, pow_eq_iterate f, hf, pow_eq_iterate, iterate_id]
    rfl

instance mulActionPowers : MulAction (powers f) α where
  one_smul _ := rfl
  mul_smul _ _ _ := rfl

theorem isPGroup_of_powers : @IsPGroup p (powers f) (groupPowers f hf) := by
  unfold IsPGroup
  intro g, hg
  use 1
  simp; congr
  rw [mem_powers_iff] at hg
  obtain k, hk := hg
  rw [ hk,  pow_mul, mul_comm, pow_mul, pow_eq_iterate f, hf, pow_eq_iterate, iterate_id]
  rfl

instance : Fintype (MulAction.fixedPoints (powers f) α) := by
  convert Set.fintypeSubset (@Set.univ α) _
  · sorry
  · simp

def key := @IsPGroup.card_modEq_card_fixedPoints _ _ (_) (isPGroup_of_powers f hf) _ α _ _ _

end Key

Jeremy Tan (Aug 15 2023 at 15:13):

Since MulAction.fixedPoints (powers f) α is of type Set α and α is already a Fintype, there should be an obvious lemma I am missing

Alex J. Best (Aug 15 2023 at 15:16):

exact? finds the answer for me

Jeremy Tan (Aug 16 2023 at 00:14):

My code's gotten big enough that I've pushed all of it to the zagier branch on mathlib4:
https://github.com/leanprover-community/mathlib4/tree/zagier

I now have a problem at the sorry on L145 of Mathlib/NumberTheory/Zagier.lean.

theorem sq_add_sq_of_nonempty_fixedPoints
    (hn : (MulAction.fixedPoints (powers (obvInvo k)) (zagierSubtype k)).Nonempty) :
     a b : , a * a + b * b = 4 * k + 1 := by
  obtain ⟨⟨⟨x, y, z⟩, he⟩, hf := hn
  rw [MulAction.mem_fixedPoints, Subtype.forall] at hf
  have := hf (obvInvo k) (mem_powers _)
  sorry
k: 
hk: Fact (Nat.Prime (4 * k + 1))
xyz: 
he: (x, y, z)  zagierSet k
hf:  (a : Function.End (zagierSubtype k)) (b : a  powers (obvInvo k)),
  { val := a, property := b }  { val := (x, y, z), property := he } = { val := (x, y, z), property := he }
this: { val := obvInvo k, property := (_ : obvInvo k  powers (obvInvo k)) }  { val := (x, y, z), property := he } =
  { val := (x, y, z), property := he }
  a b, a * a + b * b = 4 * k + 1

I want to simplify this to the condition that y = z but I can't get through the of subtypes

Jeremy Tan (Aug 16 2023 at 00:22):

Here obvInvo is the obvious involution in Zagier's proof (x, y, z) -> (x, z, y). Its fixed points correspond to representations of a 4k+1 prime as a sum of two squares

Jeremy Tan (Aug 16 2023 at 00:27):

Then there is a more complicated involution (not yet defined in the branch), defined piecewise, which Zagier shows to have exactly one fixed point (1, 1, k). His argument then goes

  • since there is exactly 1 fixed point of the complicated involution, Odd (Fintype.card (zagierSubtype k))
  • therefore (MulAction.fixedPoints (powers (obvInvo k)) (zagierSubtype k)).Nonempty by modular considerations
  • the fixed point of obvInvo gives a representation of 4 * k + 1 as a sum of two squares.

Kevin Buzzard (Aug 16 2023 at 07:47):

I thought that we already had a proof that primes which are 1 mod 4 are the sum of two squares

Johan Commelin (Aug 16 2023 at 08:17):

But not a proof that fits in the title of a PR.

Jeremy Tan (Aug 16 2023 at 09:40):

Right, now how do I get from this to y = z?

Eric Wieser (Aug 16 2023 at 09:43):

I would guess congr_arg subtype.val this followed by dsimp

Jeremy Tan (Aug 16 2023 at 11:12):

Eric Wieser said:

I would guess congr_arg subtype.val this followed by dsimp

Doesn't work. I have

theorem sq_add_sq_of_nonempty_fixedPoints
    (hn : (MulAction.fixedPoints (powers (obvInvo k)) (zagierSubtype k)).Nonempty) :
     a b : , a * a + b * b = 4 * k + 1 := by
  obtain ⟨⟨⟨x, y, z⟩, he⟩, hf := hn
  rw [MulAction.mem_fixedPoints, Subtype.forall] at hf
  have := hf (obvInvo k) (mem_powers _)
  apply_fun Subtype.val at this
  dsimp at this

but in the goal state this still has outside SMul:

this: ({ val := obvInvo k, property := (_ : obvInvo k  powers (obvInvo k)) }  { val := (x, y, z), property := he }) =
  (x, y, z)

Eric Wieser (Aug 16 2023 at 11:13):

It looks like a dsimp lemma is missing. Does change _ • _ = _ at this help?

Eric Wieser (Aug 16 2023 at 11:13):

Which instance is that ?

Jeremy Tan (Aug 16 2023 at 11:16):

That change doesn't work either. The SMul instance is

@HSMul.hSMul { x // x  powers (obvInvo k) } (zagierSubtype k) (zagierSubtype k) instHSMul
  { val := obvInvo k, property := (_ : obvInvo k  powers (obvInvo k)) } { val := (x, y, z), property := he } : zagierSubtype k

Jeremy Tan (Aug 16 2023 at 11:16):

(bear in mind you can now pull the zagier branch)

Eric Wieser (Aug 16 2023 at 11:16):

What's the instHSMul there?

Jeremy Tan (Aug 16 2023 at 11:17):

@instHSMul { x // x  powers (obvInvo k) } (zagierSubtype k) MulAction.toSMul : HSMul { x // x  powers (obvInvo k) } (zagierSubtype k) (zagierSubtype k)

Eric Wieser (Aug 16 2023 at 11:17):

And the MulAction.toSMul? you want to trace it back until you're past all the Foo.toBar instances

Jeremy Tan (Aug 16 2023 at 11:17):

@MulAction.toSMul { x // x  powers (obvInvo k) } (zagierSubtype k) (toMonoid (powers (obvInvo k)))
  (mulActionPowers (obvInvo k)) : SMul { x // x  powers (obvInvo k) } (zagierSubtype k)

Eric Wieser (Aug 16 2023 at 11:18):

Is mulActionPowers your own instance?

Jeremy Tan (Aug 16 2023 at 11:18):

Yes (it's defined in L92 of Zagier.lean in the branch)

Jeremy Tan (Aug 16 2023 at 11:18):

instance mulActionPowers : MulAction (powers f) α where
  one_smul _ := rfl
  mul_smul _ _ _ := rfl

Eric Wieser (Aug 16 2023 at 11:19):

Does rw [Submonoid.smul_def] at this (then dsimp) make progress?

Jeremy Tan (Aug 16 2023 at 11:21):

Now _that_ works:

theorem sq_add_sq_of_nonempty_fixedPoints
    (hn : (MulAction.fixedPoints (powers (obvInvo k)) (zagierSubtype k)).Nonempty) :
     a b : , a * a + b * b = 4 * k + 1 := by
  obtain ⟨⟨⟨x, y, z⟩, he⟩, hf := hn
  rw [MulAction.mem_fixedPoints, Subtype.forall] at hf
  have := hf (obvInvo k) (mem_powers _)
  apply_fun Subtype.val at this
  rw [Submonoid.smul_def, End.smul_def] at this
  dsimp at this

Jeremy Tan (Aug 16 2023 at 11:21):

After the dsimp I have this: ↑(obvInvo k { val := (x, y, z), property := he }) = (x, y, z)

Eric Wieser (Aug 16 2023 at 11:23):

Sounds like you forgot to teach lean that obvInvo was obvious

Jeremy Tan (Aug 16 2023 at 11:25):

Full proof:

theorem sq_add_sq_of_nonempty_fixedPoints
    (hn : (MulAction.fixedPoints (powers (obvInvo k)) (zagierSubtype k)).Nonempty) :
     a b : , a * a + b * b = 4 * k + 1 := by
  obtain ⟨⟨⟨x, y, z⟩, he⟩, hf := hn
  rw [MulAction.mem_fixedPoints, Subtype.forall] at hf
  have := hf (obvInvo k) (mem_powers _)
  apply_fun Subtype.val at this
  rw [Submonoid.smul_def, End.smul_def] at this
  unfold obvInvo at this; simp at this
  unfold zagierSet at he; simp at he
  use x, (2 * y)
  rw [this.1, show 4 * y * y = 2 * y * (2 * y) by linarith] at he
  assumption

Jeremy Tan (Aug 17 2023 at 09:22):

THE PROOF IS FINISHED
#6629

Damiano Testa (Aug 17 2023 at 10:49):

This is a really long line!

Jeremy Tan (Aug 18 2023 at 03:34):

@Eric Wieser @Alex J. Best I have responded to your reviews

Jeremy Tan (Aug 22 2023 at 07:24):

@Thomas Browning how to prove the sorry below? The function is in GroupTheory.Perm.Cycle.Type after card_compl_support_modEq

/-- The number of fixed points of a `p ^ n`-th root of the identity function over a finite set
and the set's cardinality have the same residue modulo `p`, where `p` is a prime. -/
theorem card_modEq_card_fixedPoints_of_pow_prime [DecidableEq α] {f : Function.End α} {p n : }
    [hp : Fact p.Prime] (hf : f ^ p ^ n = 1) :
    Fintype.card α  Fintype.card f.fixedPoints [MOD p] := by
  let σ : α  α := f, f ^ (p ^ n - 1),
  by
    simp_rw [Function.LeftInverse,  Function.comp_apply (g := f),
      show (f ^ (p ^ n - 1))  f = f ^ (p ^ n - 1) * f by rfl,  pow_succ',
      Nat.sub_add_cancel (pow_pos hp.out.pos n)]
    exact congrFun hf,
  by
    simp_rw [Function.RightInverse, Function.LeftInverse,  Function.comp_apply (f := f),
      show f  (f ^ (p ^ n - 1)) = f * f ^ (p ^ n - 1) by rfl,  pow_succ,
      Nat.sub_add_cancel (pow_pos hp.out.pos n)]
    exact congrFun hf
  have  : σ ^ p ^ n = 1 := by
    sorry
  suffices : Fintype.card f.fixedPoints = (support σ)ᶜ.card
  · exact this  (card_compl_support_modEq ).symm
  suffices : f.fixedPoints = (support σ)
  · simp only [this]; apply Fintype.card_coe
  simp [Set.ext_iff, Function.IsFixedPt]

Thomas Browning (Aug 22 2023 at 07:35):

Yes, it's more painful than it ought to be. I answered on github.

Jeremy Tan (Aug 22 2023 at 08:20):

It does not seem to help if I define npow on instMonoidEnd as follows:

instance : Monoid (Function.End α) where
  one := id
  mul := (·  ·)
  mul_assoc f g h := rfl
  mul_one f := rfl
  one_mul f := rfl
  npow n f := f^[n]
  npow_zero _ := rfl
  npow_succ _ _ := by simp only [Function.iterate_succ']; rfl

Jeremy Tan (Aug 22 2023 at 08:26):

However, a less hacky way might be to override npow in instMonoidEnd

Yeah, I've overridden it, now what?

Eric Wieser (Aug 22 2023 at 09:57):

I don't think you should be refactoring that in that PR

Jeremy Tan (Aug 22 2023 at 11:10):

@Eric Wieser I have not committed the npow override to my PR


Last updated: Dec 20 2023 at 11:08 UTC