Zulip Chat Archive

Stream: new members

Topic: imo problems that are challenging to formalize


Horst Staley (Jul 19 2023 at 04:29):

Hello everyone :wave:

I am interested in getting my hands dirty with Lean4 by formalizing some IMO problems (hopefully can also make some useful contributions to mathlib on the way) ...

can someone point me to some IMO problems that are known to be difficult to formalize ... I can tell the geometry ones are challenging, but are there other ones as well?

Thanks in advance!

Scott Morrison (Jul 19 2023 at 04:31):

I'm not sure you'll find someone with a ready answer for you. One simple answer is anything that hasn't yet been formalized!

Scott Morrison (Jul 19 2023 at 04:32):

The geometry problems are difficult because they need a lot of Mathlib development to build good API --- but that is not what a beginner wants to tackle!

Horst Staley (Jul 19 2023 at 04:36):

Thanks @Scott Morrison that was definitely my plan B ... if nobody pointed out particularly interesting or challenging ones, I will just take a random one :)

Scott Morrison (Jul 19 2023 at 04:37):

The basic problem is that "difficult to formalize" doesn't correlate at all well with "difficult as an exam question". Any generally "difficult to formalize" means "you have to design new API in Mathlib", which is not what you're looking for initially.

Scott Morrison (Jul 19 2023 at 04:38):

If you're just looking for "difficult as an exam question", start with Q6s. :-)

Horst Staley (Jul 19 2023 at 04:39):

nono, definitely not ... I'm just looking for difficult to formalize (and I was thinking of starting with just the problem statements)

Horst Staley (Jul 19 2023 at 04:40):

if I just wanted to solve hard math problems, I have my chalkboard, no need for lean :D

Scott Morrison (Jul 19 2023 at 04:40):

Much better exercise to do the proofs. :-)

Joseph Myers (Jul 19 2023 at 11:32):

It's hard to be sure your formal statement is correct if you don't formalize a proof (consider the case of an AI that claimed a solution to a hard problem that had been wrongly formalized using subtraction).

Having a detailed written informal solution is important before starting formalizing (see e.g. The IMO Compendium (for 1959-2009) or shortlist booklets (2006-2022) (but watch out for the version of a problem in the shortlist differing significantly from the version on the final exam) or the AoPS wiki).

See also archive/imo/README.md (in mathlib3, one of the miscellaneous .md files not yet ported to mathlib4) for more discussion of IMO formalizations.

David Renshaw (Jul 19 2023 at 12:30):

FYI, I've been doing a bunch of olympiad formalization here and contributions are welcome.

Joseph Myers (Jul 19 2023 at 23:37):

I think all 386 past IMO problems would be appropriate for the mathlib archive (we currently have 32 of them, for an average of half a problem per IMO), as would problems from other (e.g. national / regional) olympiads (or proof-based mathematics competitions in general) such as you have in that repository, if brought up to mathlib standards (including in particular factoring out any results of more general use and putting those in mathlib proper). Of course getting something up to mathlib standards may be a lot of work - I don't expect to convert my British MO formalizations to Lean 4 or to attempt to get them up to mathlib standards.

Eric Wieser (Jul 20 2023 at 16:25):

Joseph Myers said:

See also archive/imo/README.md (in mathlib3, one of the miscellaneous .md files not yet ported to mathlib4) for more discussion of IMO formalizations.

#6031

Yury G. Kudryashov (Jul 20 2023 at 18:50):

Do we have a list of files/webpages that we should migrate? The style guide still talks about Lean 3.

Yury G. Kudryashov (Jul 20 2023 at 18:54):

I left some comments on #6031

Joseph Myers (Jul 21 2023 at 00:52):

I think there are some additional .md files to migrate (CITATION.md for example), though of course not all the placeholder files that say that some documentation was moved to the website. And the whole website needs updating to Lean 4 where not already done.

Horst Staley (Jul 23 2023 at 23:47):

Thanks @Joseph Myers

Horst Staley (Jul 29 2023 at 18:34):

Hello everyone, I have decided to start with IMO 1961 Q3

def ProblemEquation (n : ) (x : ) : Prop :=
  (cos x)^n - (sin x)^n = 1

def evenSet : Set  :=
  {x :  |  k : , x = k * π}

def oddSet : Set  :=
  {x :  |  k : ,
  x = ((4 * k - 1) * (π / 2)) 
  x = ((4 * k) * (π / 2))}

theorem imo1961_q3 {n : } {x : } : (Even n  ProblemEquation n x 
  (x  evenSet))  (Odd n  ProblemEquation n x  x  oddSet) := by
  constructor

Before I started cranking on the proof, I just wanted to doublecheck that I've set it up in the best possible way ... I appreciate any feedback! :pray:

David Renshaw (Jul 29 2023 at 18:50):

In this problem, part of the answer is actually coming up with the solution set, and your setup does not really surface that.

David Renshaw (Jul 29 2023 at 18:50):

I would do something more like

def solutionSet (n : ) : Set  :=
  if Even n
  then { x :  |  k : , x = k * π}
  else { x :  |  k : ,
         x = ((4 * k - 1) * (π / 2)) 
         x = ((4 * k) * (π / 2))}

theorem imo1961_q3 {n : } {x : } :
    (cos x)^n - (sin x)^n = 1  x  solutionSet n := by
  sorry

David Renshaw (Jul 29 2023 at 18:51):

And I think we're eventually going to want some kind of annotation that we can put on that solutionSet def, to make it clear that supplying that term is supposed to be part of the problem.

David Renshaw (Jul 29 2023 at 18:54):

Lately I've been adding a -- @[solution_data] commented-out (fake) annotation for such defs, as here: https://github.com/dwrensha/math-puzzles-in-lean4/blob/ea6cedd064e12e7853c8e8fed89e3d585ac3ce54/MathPuzzles/Usa1998Q4.lean#L53-L54

Horst Staley (Jul 29 2023 at 19:19):

thank you, much more elegant

Horst Staley (Jul 30 2023 at 17:21):

@David Renshaw or others, is there an example of how to construct the solutionSet somehow within a Lean environment?

Seems like most of the answers here figure it out via pen and paper ...

David Renshaw (Jul 30 2023 at 17:52):

You want to automatically fill in the term for solutionSet? That's really difficult, but it's ultimately something we'll need to do as part of the IMO Grand Challenge.

David Renshaw (Jul 30 2023 at 17:53):

Hm... I suppose a tricky aspect is that if you are filling in the term in tactic mode, you don't have easy access to the later definition imo1961_q3 where the def is used.

Horst Staley (Jul 30 2023 at 17:55):

eventually yes, but at first I was thinking just demonstrating that it could be done manually in the Lean environment would be a good step

David Renshaw (Jul 30 2023 at 17:56):

what do you mean by "in the Lean environment"?

Horst Staley (Jul 30 2023 at 17:58):

I mean, a sequence of steps/tactics that would begin with just (cos x)^n - (sin x)^n = 1, and end up with the contents of solutionSet ...

Horst Staley (Jul 30 2023 at 17:59):

maybe the best analogue would be to scratch work?

Horst Staley (Jul 30 2023 at 18:00):

hopefully what I am saying makes sense, I am new to Lean

Eric Wieser (Jul 30 2023 at 18:06):

In Lean 3 it was possible to write:

def the_problem (ans : nat) : Prop := 1 + 2 = ans

-- this should be a theorem, but if you make it a def then the `_` can be filled in later
def obvious : the_problem _ := rfl

#check obvious -- the_problem (1 + 2)

David Renshaw (Jul 30 2023 at 18:10):

I like the word "proplem", but I don't understand what Eric is saying

David Renshaw (Jul 30 2023 at 18:11):

In our case we could do

theorem imo1961_q3 {n : } (solutionSet: Set ) {x : } :
    (cos x)^n - (sin x)^n = 1  x  solutionSet := by sorry

and then ... ?

Eric Wieser (Jul 30 2023 at 18:15):

The point is that in Lean 3 you could use a def where you would normally use a theorem, and it leaves a metavariable to solve mid-proof

David Renshaw (Jul 30 2023 at 18:17):

interesting

Horst Staley (Jul 30 2023 at 18:23):

is there a way to do this in Lean4?

Horst Staley (Jul 30 2023 at 19:26):

is there a better channel to get feedback on my lean code? or should I just keep posting it here

Kevin Buzzard (Jul 30 2023 at 19:40):

Posting here is fine

Horst Staley (Jul 30 2023 at 19:44):

(deleted)

Kevin Buzzard (Jul 30 2023 at 19:47):

Uploading code by attaching it is quite inconvenient, eg I can't see it on mobile. Just paste the code in between triple backticks unless it's well over 100 lines in which case link to a gist

Horst Staley (Jul 30 2023 at 19:48):

Sorry I’m also on mobile :)

Horst Staley (Jul 30 2023 at 19:49):

import Mathlib.Data.Real.Basic
import Mathlib.Data.Nat.Basic
import Mathlib.Analysis.SpecialFunctions.Trigonometric.Complex
import Mathlib.Tactic.Linarith

open Real
open Nat

lemma sin_even_nonneg (x : ) (n : )
(even_n : Even n) : 0  sin x ^ n :=
by
  rcases even_n with r, hr
  rw [hr]
  rw [ two_mul]
  rw [rpow_nat_cast]
  rw [pow_mul]
  apply pow_nonneg
  apply sq_nonneg

lemma cos_pow_ge_one (x : ) (n : )
(even_n : Even n)
(f : cos x ^ n = 1 + sin x ^ n) : cos x ^ n  1 := by
  rw [f]
  apply le_add_of_nonneg_right
  exact sin_even_nonneg x n even_n

lemma abs_cos_pow_le_one (x : ) (n : ) : abs (cos x) ^ n  1 := by
  apply rpow_le_one
  apply abs_nonneg
  apply abs_cos_le_one
  apply cast_nonneg

lemma cos_pow_le_one (x : ) (n : ) : (cos x) ^ n  1 := by
  have f := le_abs_self ((cos x) ^ n)
  have g := abs_cos_pow_le_one x n
  have h := abs_rpow_le_abs_rpow (cos x) n
  have j := le_trans f h
  have k := le_trans j g
  exact k

lemma sin_eq_zero_if_n_even_and_f (x : ) (n : ) (even_n : Even n) :
(cos x)^n - (sin x)^n = 1  sin x = 0 := by
  rw [sub_eq_iff_eq_add]
  intro f
  have g := cos_pow_ge_one x n even_n f
  have h := cos_pow_le_one x n
  have k := le_antisymm h g
  have l := congr_arg abs k
  rw [abs_one] at l
  rw [rpow_nat_cast] at l
  rw [abs_pow_eq_one] at l
  have m := eq_or_eq_neg_of_abs_eq l
  rw [ @sin_eq_zero_iff_cos_eq x] at m
  exact m
  apply Nat.pos_of_ne_zero
  rw [k] at f
  contrapose f
  rw [ neZero_iff] at f
  rw [not_neZero] at f
  intro f_1
  rw [f] at f_1
  rw [rpow_nat_cast] at f_1
  rw [_root_.pow_zero] at f_1
  norm_num at f_1

lemma f_holds_if_n_nonzero_even_and_x_integer_multiple_of_pi (x : ) (n : ) (k : )
(n_zero : n  0) (even_n : Even n) : x = k * π 
cos x ^ n - sin x ^ n = 1 := by
  intro f
  have h :  k : , k * π = x
  use k
  exact symm f
  rw [ sin_eq_zero_iff] at h
  rw [h]
  rw [sin_eq_zero_iff_cos_eq] at h
  rcases h with h1 | h2
  rw [h1]
  norm_num
  exact Nat.pos_of_ne_zero n_zero
  rw [h2, rpow_nat_cast, rpow_nat_cast, zero_pow, sub_zero,
  neg_one_pow_eq_one_iff_even]
  exact even_n
  norm_num
  exact Nat.pos_of_ne_zero n_zero

-- @[solution_data]
def solutionSet (n : ) : Set  :=
  if n = 0
  then 
  else if Even n
  then { x :  |  k : , x = k * π}
  else { x :  |  k : ,
         x = ((4 * k - 1) * (π / 2)) 
         x = ((4 * k) * (π / 2))}

theorem imo1961_q3 {x : } {n : } :
  (cos x)^n - (sin x)^n = 1  x  solutionSet n := by
  rw [solutionSet]
  split_ifs with n_zero n_even
  constructor

  -- case n=0
  intro f
  rw [rpow_nat_cast, rpow_nat_cast, sub_eq_iff_eq_add, n_zero, _root_.pow_zero,
  _root_.pow_zero, one_add_one_eq_two] at f
  norm_num at f
  exfalso

  -- case n even, forward direction
  constructor
  intro f
  have g := sin_eq_zero_if_n_even_and_f x n n_even f
  rw [sin_eq_zero_iff] at g
  rcases g with k, g1
  constructor
  exact symm g1

  -- case n even, reverse direction
  intro f
  rcases f with a, b
  exact f_holds_if_n_nonzero_even_and_x_integer_multiple_of_pi x n a n_zero n_even b

  --case n odd
  sorry

Kevin Buzzard (Jul 30 2023 at 19:51):

Edit the post to use ``` at top and bottom (you've used the wrong ticks)

Kevin Buzzard (Jul 30 2023 at 19:52):

sin_even_nonneg shouldn't exist in that form -- any real raised to an even power is nonnegative. Make the result more general and change the name?

Kevin Buzzard (Jul 30 2023 at 19:54):

cos_pow_le_one has a much more elegant proof as a three line calc block

Kevin Buzzard (Jul 30 2023 at 19:58):

sin_eq_zero_if_n_even : lemma names shouldn't have if or an and in -- take a look at the #naming convention. We use of for both. and would only be in the name of a lemma which explicitly mentioned the logical \land symbol

Kevin Buzzard (Jul 30 2023 at 20:00):

The layout of the sin_eq_zero_if_n_even proof is poor -- you should never have two open goals in your context; when this happens you need to indent. If you don't do this it makes proofs very hard to read away from lean

Kevin Buzzard (Jul 30 2023 at 20:00):

Nice job though -- you're half way there!

Horst Staley (Jul 30 2023 at 20:01):

2/3 :) if you consider the n=0 case

Horst Staley (Jul 30 2023 at 20:02):

Thanks!

Horst Staley (Aug 04 2023 at 19:29):

OK, I just had the time to do another pass, would you mind critiquing again?

import Mathlib.Data.Real.Basic
import Mathlib.Data.Nat.Basic
import Mathlib.Analysis.SpecialFunctions.Trigonometric.Complex
import Mathlib.Tactic.Linarith

open Real
open Nat

lemma rpow_even_nonneg {x : } {n : }
(even_n : Even n) : 0  x ^ n := by
  rcases even_n with r, hr
  rw [hr, two_mul, rpow_nat_cast, mul_comm, pow_mul]
  have g:= sq_nonneg (x^r)
  rw [rpow_nat_cast] at g
  exact g

lemma cos_pow_ge_one {x : } {n : }
(even_n : Even n) (f : cos x ^ n = 1 + sin x ^ n) : cos x ^ n  1 := by
  rw [f]
  apply le_add_of_nonneg_right
  exact rpow_even_nonneg even_n

lemma abs_cos_pow_le_one {x : } {n : } : abs (cos x) ^ n  1 := by
  apply rpow_le_one
  apply abs_nonneg
  apply abs_cos_le_one
  apply cast_nonneg

lemma cos_pow_le_one {x : } {n : } : (cos x) ^ n  1 :=
  calc
    (cos x) ^ n  abs ((cos x) ^ n) := le_abs_self ((cos x)^n)
    _            abs (cos x) ^ n   := abs_rpow_le_abs_rpow (cos x) n
    _            1                 := abs_cos_pow_le_one

lemma sin_eq_zero_of_even_f {x : } {n : } (even_n : Even n) :
(cos x)^n - (sin x)^n = 1  sin x = 0 := by
  rw [sub_eq_iff_eq_add]
  intro f
  if hn : n = 0 then
    rw [rpow_nat_cast, rpow_nat_cast] at f
    rw [hn] at f
    norm_num at f
  else
    have g :=
    congr_arg abs (le_antisymm (@cos_pow_le_one x n) (cos_pow_ge_one even_n f))
    rw [abs_one, rpow_nat_cast, abs_pow_eq_one (cos x) (Nat.pos_of_ne_zero hn)] at g
    have h := eq_or_eq_neg_of_abs_eq g
    rw [ @sin_eq_zero_iff_cos_eq x] at h
    exact h

lemma exists_integer_of_integer {x : } {k : } : x = k * π   k : , k * π = x := by
  intro f
  use k
  exact symm f

lemma f_holds_of_n_nonzero_even_x_int_multiple_of_pi {x : } {n : } {k : }
(n_zero : n  0) (even_n : Even n) : x = k * π 
cos x ^ n - sin x ^ n = 1 := by
  intro f
  have g := exists_integer_of_integer f
  have h := Nat.pos_of_ne_zero n_zero
  rw [ sin_eq_zero_iff] at g
  rw [g]
  rw [sin_eq_zero_iff_cos_eq] at g
  apply Or.elim g
  . intro g1
    rw [g1]
    norm_num
    exact Nat.pos_of_ne_zero n_zero
  . intro g2
    rw [g2, rpow_nat_cast, rpow_nat_cast, zero_pow h, sub_zero, neg_one_pow_eq_one_iff_even]
    exact even_n
    norm_num

-- @[solution_data]
def solutionSet (n : ) : Set  :=
  if n = 0
  then 
  else if Even n
  then { x :  |  k : , x = k * π}
  else { x :  |  k : ,
         x = ((4 * k - 1) * (π / 2)) 
         x = ((4 * k) * (π / 2))}

theorem imo1961_q3 {x : } {n : } :
  (cos x)^n - (sin x)^n = 1  x  solutionSet n := by
  rw [solutionSet]
  split_ifs with n_zero n_even
  constructor

  -- case n=0
  intro f
  rw [rpow_nat_cast, rpow_nat_cast, sub_eq_iff_eq_add, n_zero, _root_.pow_zero,
  _root_.pow_zero, one_add_one_eq_two] at f
  norm_num at f
  exfalso

  -- case n even, forward direction
  constructor
  intro f
  have g := sin_eq_zero_of_even_f n_even f
  rw [sin_eq_zero_iff] at g
  rcases g with k, g1
  constructor
  exact symm g1

  -- case n even, reverse direction
  intro f
  rcases f with a, b
  exact f_holds_of_n_nonzero_even_x_int_multiple_of_pi n_zero n_even b

  --case n odd
  sorry

Horst Staley (Aug 04 2023 at 19:29):

The exists_integer_of_integer lemma seemed a bit hacky to me, but i couldn’t figure out a simpler way to transform it

David Renshaw (Aug 04 2023 at 20:50):

Instead of pulling that out as a lemma, you could directly do

  have g :  k : , k * π = x := k, f.symm

Ioannis Konstantoulas (Aug 07 2023 at 20:05):

Joseph Myers said:

It's hard to be sure your formal statement is correct if you don't formalize a proof (consider the case of an AI that claimed a solution to a hard problem that had been wrongly formalized using subtraction).

Can you link to that story?

Joseph Myers (Aug 08 2023 at 00:11):

https://arxiv.org/pdf/2205.11491.pdf (last page, proof of an incorrect version of IMO 2001 problem 6).


Last updated: Dec 20 2023 at 11:08 UTC