Zulip Chat Archive

Stream: Is there code for X?

Topic: Integer is not one half


Aaron Liu (Jun 25 2025 at 15:57):

Is there a quick way to prove this? I know I can multiply both sides by two, convert to equality in the integers, and then argue that the lhs is even but the rhs is odd. However, this seems like a bit much just for such a simple-seeming fact.

import Mathlib

example (x : ) : (x : )  2⁻¹ := by
  sorry

Aaron Liu (Jun 25 2025 at 16:01):

If you can make it work for an arbitrary denominator d in a division ring with characteristic not dividing d that would be great too

Damiano Testa (Jun 25 2025 at 16:05):

example (x : ) : (x : )  2⁻¹ := by
  rw [ne_eq,  mul_one 2⁻¹, eq_inv_mul_iff_mul_eq₀ two_ne_zero]
  norm_cast
  omega

Damiano Testa (Jun 25 2025 at 16:06):

Oh, I had not read that this is what you already had tried! :man_facepalming:

Aaron Liu (Jun 25 2025 at 16:06):

That's three whole lines, I was hoping for something shorter. Thanks anyways!

Damiano Testa (Jun 25 2025 at 16:07):

There should be a lemma that says that an integers that is less than 1 in absolute value is zero.

Damiano Testa (Jun 25 2025 at 16:08):

docs#Int.abs_lt_one_iff I am not sure if it can be useful here.

Kenny Lau (Jun 25 2025 at 16:49):

my gut says you should prove that it's between 0 and 1 (by norm_num), and that should give you a contradiction

Kenny Lau (Jun 25 2025 at 16:49):

(and if it doesn't work, then that means we're missing lemmas)

Robin Arnez (Jun 25 2025 at 17:17):

example (x : ) : (x : )  2⁻¹ := by
  apply_fun (fun x :  => x - x)
  norm_num

Ruben Van de Velde (Jun 25 2025 at 18:32):

I would suggest apply_fun Int.fract, but norm_num doesn't support that

Kyle Miller (Jun 25 2025 at 18:38):

Another option:

example (x : ) : (x : )  2⁻¹ := by
  field_simp; norm_cast; omega

Kenny Lau (Jun 25 2025 at 18:40):

We really don't have the lemma I said? (there is no integer between n and n+1)

Ruben Van de Velde (Jun 25 2025 at 18:40):

How would you state it?

Kenny Lau (Jun 25 2025 at 18:46):

import Mathlib

theorem Int.cast_ne_inv_two (x : ) : (x : )  2⁻¹ := by
  intro hx
  have cast_x_pos : 0 < (x : ) := by rw [hx]; norm_num
  have x_pos : 0 < x := by assumption_mod_cast
  rw [Int.lt_iff_add_one_le] at x_pos
  have one_le_x : (1 : )  x := by assumption_mod_cast
  rw [hx] at one_le_x
  norm_num at one_le_x

Kenny Lau (Jun 25 2025 at 18:47):

this is close to the proof i stated

Aaron Liu (Jun 25 2025 at 18:47):

the point is to make it short

Ruben Van de Velde (Jun 25 2025 at 18:49):

example (x : ) : (x : )  2⁻¹ := by
  apply Int.cast_mono.ne_of_lt_of_lt_int 0 <;> norm_num

Kenny Lau (Jun 25 2025 at 18:53):

import Mathlib

#check Nat.le_and_le_add_one_iff -- note that the theorem exists for `ℕ`

theorem Int.le_and_le_add_one_iff {n m : } : n  m  m  n + 1  m = n  m = n + 1 := by omega

theorem Int.not_lt_and_lt_add_one {n m : } : ¬(n < m  m < n + 1) := by omega

theorem Int.cast_ne_inv_two (x : ) : (x : )  2⁻¹ :=
  fun hx  Int.not_lt_and_lt_add_one (n := 0) (m := x)
    (by rw [ Int.cast_lt (R := ), hx,  Int.cast_lt (R := ), hx]; norm_num)
  -- rw_mod_cast was a bit weak there

This is the proof I had in mind

Kenny Lau (Jun 25 2025 at 18:53):

if only i could use rw_mod_cast

Kenny Lau (Jun 25 2025 at 18:53):

ah nice @Ruben Van de Velde you chained two theorems to get the one I wanted

Kenny Lau (Jun 25 2025 at 18:54):

do we think rw_mod_cast should cover this usecase btw?

Kenny Lau (Jun 25 2025 at 19:14):

import Mathlib

theorem Int.cast_ne_inv_two (x : ) : (x : )  2⁻¹ := by
  refine (mul_left_inj' Real.pi_ne_zero).ne.1 (Real.sin_ne_zero_iff.1 ?_ x)
  rw [inv_mul_eq_div, Real.sin_pi_div_two]; simp

Kenny Lau (Jun 25 2025 at 19:16):

we should really have computable reals, then we can just decide everything :melt:

Kenny Lau (Jun 25 2025 at 19:16):

like now the proof I want is to convert this to a statement in Q, and then decide it

Kenny Lau (Jun 25 2025 at 19:19):

... we have Rat.isInt : ℚ -> Bool but not the proof that it actually does what it says

Aaron Liu (Jun 25 2025 at 19:20):

What about docs#Rat.eq_num_of_isInt

Aaron Liu (Jun 25 2025 at 19:20):

I guess we don't have the reverse direction

Aaron Liu (Jun 25 2025 at 19:20):

But the reverse direction is also just rfl

Kenny Lau (Jun 25 2025 at 19:20):

oh wait there is some CanLift stuff just below

Kenny Lau (Jun 25 2025 at 19:29):

import Mathlib

theorem Rat.isInt_iff (q : ) : q.isInt   x : , x = q :=
  fun h  Rat.canLift.prf _ (eq_of_beq h), fun ⟨_, hn  hn  rfl

theorem Int.cast_ne_inv_two (x : ) : (x : )  2⁻¹ := by
  rw [show (2⁻¹ : ) = (2⁻¹ : ) by simp]
  intro h
  exact Ne.elim (by decide) ((Rat.isInt_iff (2⁻¹)).2 x, by exact_mod_cast h)
  -- doesn't work

Why does this decide not work??

Aaron Liu (Jun 25 2025 at 19:29):

Is Rat.inv irreducible?

Kenny Lau (Jun 25 2025 at 19:30):

ok +kernel works then

import Mathlib

theorem Rat.isInt_iff (q : ) : q.isInt   x : , x = q :=
  fun h  Rat.canLift.prf _ (eq_of_beq h), fun ⟨_, hn  hn  rfl

theorem Int.cast_ne_inv_two (x : ) : (x : )  2⁻¹ := by
  rw [show (2⁻¹ : ) = (2⁻¹ : ) by simp]
  intro h
  exact Ne.elim (by decide +kernel) ((Rat.isInt_iff (2⁻¹)).2 x, by exact_mod_cast h)

Kenny Lau (Jun 25 2025 at 19:30):

also I wish the mod_cast stuff was more powerful so that I can omit the first rw lol

Kenny Lau (Jun 25 2025 at 19:35):

import Mathlib

theorem Rat.isInt_iff (q : ) : q.isInt   x : , x = q :=
  fun h  Rat.canLift.prf _ (eq_of_beq h), fun ⟨_, hn  hn  rfl

instance (q : ) : Decidable ( x : , x = q) :=
  decidable_of_decidable_of_iff q.isInt_iff

theorem Int.cast_ne_inv_two (x : ) : (x : )  2⁻¹ := by
  rw [show (2⁻¹ : ) = (2⁻¹ : ) by simp]
  norm_cast; revert x; rw [ not_exists]; decide +kernel

Aaron Liu (Jun 25 2025 at 19:36):

Why Rat.canLift.prf?

Kenny Lau (Jun 25 2025 at 19:36):

idk how else to do it

Aaron Liu (Jun 25 2025 at 19:37):

We have Rat.eq_num_of_isInt

Kenny Lau (Jun 25 2025 at 19:37):

that works too, but is not really shorter

Aaron Liu (Jun 25 2025 at 19:38):

I guess that's true

Kenny Lau (Jun 25 2025 at 19:39):

import Mathlib

theorem Rat.isInt_iff (q : ) : q.isInt   x : , x = q :=
  fun h  ⟨_, (eq_num_of_isInt h).symm, fun ⟨_, hn  hn  rfl

instance (q : ) : Decidable ( x : , x = q) :=
  decidable_of_decidable_of_iff q.isInt_iff

instance (q : ) : Decidable ( x : , (x : )  q) :=
  decidable_of_decidable_of_iff not_exists

theorem Int.cast_ne_inv_two (x : ) : (x : )  2⁻¹ := by
  rw [show (2⁻¹ : ) = (2⁻¹ : ) by simp]
  norm_cast; decide +revert +kernel

Yaël Dillies (Jun 25 2025 at 20:25):

My gut feeling is to reduce your statement to Int.fract ... != 0 and run norm_num

Ruben Van de Velde (Jun 25 2025 at 20:30):

Ruben Van de Velde said:

I would suggest apply_fun Int.fract, but norm_num doesn't support that

Ruben Van de Velde (Jun 25 2025 at 20:31):

I tried to add support by blindly copy/pasting code around, but somehow it didn't really work

Eric Wieser (Jun 26 2025 at 01:04):

At one point this was on my to-do list

Eric Wieser (Jun 26 2025 at 01:05):

Maybe make a draft PR with what you have?

Ruben Van de Velde (Jun 26 2025 at 09:00):

Eric Wieser said:

Maybe make a draft PR with what you have?

#26428


Last updated: Dec 20 2025 at 21:32 UTC