Zulip Chat Archive

Stream: maths

Topic: How to prove 1/2 is not integral over Z ?


Qingfeng Li (Sep 17 2025 at 06:53):

How to prove that:

import Mathlib

example : ¬ IsIntegral  (1 / 2 : ) := by
  sorry

In math we try to show the minpoly is 2x-1 which is not monic, but in mathlib it's illegal because the definition of minpoly is monic.

Riccardo Brasca (Sep 17 2025 at 07:04):

We know that is integrally closed, so this should be easy.

Riccardo Brasca (Sep 17 2025 at 07:17):

Something like

import Mathlib

example : ¬ IsIntegral  (1 / 2 : ) := by
  intro h
  obtain x, hx := ((isIntegrallyClosed_iff_isIntegrallyClosedIn ).1 inferInstance).isIntegral_iff.1 h
  apply_fun (· * 2) at hx
  replace hx : (x : ) * ((2 : ) : ) = 1 := by
    simpa using hx
  norm_cast at hx
  rcases Int.mul_eq_one_iff_eq_one_or_neg_one.1 hx with ⟨_, h | ⟨_, h <;>
  norm_num at h

Riccardo Brasca (Sep 17 2025 at 07:17):

Note that most of the proof is to show that 1/2 is not an integer.

Ruben Van de Velde (Sep 17 2025 at 07:32):

Shorter (*):

import Mathlib


section NormNum -- #26428
open Mathlib.Meta.NormNum Qq Int

variable {α : Type*} [Field α] [LinearOrder α] [IsStrictOrderedRing α] [FloorRing α]
variable {R : Type*} [Ring R] [LinearOrder R] [IsStrictOrderedRing R] [FloorRing R]
theorem isNat_intFract_of_isNat (r : R) (m : ) : IsNat r m  IsNat (Int.fract r) 0 := by
  rintro ⟨⟨⟩⟩; exact by simp

theorem isNat_intFract_of_isInt (r : R) (m : ) : IsInt r m  IsNat (Int.fract r) 0 := by
  rintro ⟨⟨⟩⟩; exact by simp

theorem isNNRat_intFract_of_isNNRat (r : α) (n d : ) :
    IsNNRat r n d  IsNNRat (Int.fract r) (n % d) d := by
  rintro inv, rfl
  refine inv, ?_⟩
  simp only [invOf_eq_inv,  div_eq_mul_inv, fract_div_natCast_eq_div_natCast_mod]

theorem isRat_intFract_of_isRat_negOfNat (r : α) (n d : ) :
    IsRat r (negOfNat n) d  IsRat (Int.fract r) (-n % d) d := by
  rintro inv, rfl
  refine inv, ?_⟩
  simp only [invOf_eq_inv,  div_eq_mul_inv, fract_div_intCast_eq_div_intCast_mod,
    negOfNat_eq, ofNat_eq_coe]

/-- `norm_num` extension for `Int.fract` -/
@[norm_num (Int.fract _)]
def evalIntFract : NormNumExt where eval {u α} e := do
  match e with
  | ~q(@Int.fract _ $instR $instO $instF $x) =>
    match  derive x with
    | .isBool .. => failure
    | .isNat _ _ pb => do
      let _i  synthInstanceQ q(IsStrictOrderedRing $α)
      assertInstancesCommute
      have z : Q() := Lean.mkRawNatLit 0
      letI : $z =Q 0 := ⟨⟩
      return .isNat _ z q(isNat_intFract_of_isNat $x _ $pb)
    | .isNegNat _ _ pb => do
      let _i  synthInstanceQ q(IsStrictOrderedRing $α)
      assertInstancesCommute
      have z : Q() := Lean.mkRawNatLit 0
      letI : $z =Q 0 := ⟨⟩
      return .isNat _ z q(isNat_intFract_of_isInt _ _ $pb)
    | .isNNRat _ q n d h => do
      let _i  synthInstanceQ q(Field $α)
      let _i  synthInstanceQ q(IsStrictOrderedRing $α)
      assertInstancesCommute
      have n' : Q() := Lean.mkRawNatLit (q.num.natAbs % q.den)
      letI : $n' =Q $n % $d := ⟨⟩
      return .isNNRat _ (Int.fract q) n' d q(isNNRat_intFract_of_isNNRat _ $n $d $h)
    | .isNegNNRat _ q n d h => do
      let _i  synthInstanceQ q(Field $α)
      let _i  synthInstanceQ q(IsStrictOrderedRing $α)
      assertInstancesCommute
      have n' : Q() := mkRawIntLit (q.num % q.den)
      letI : $n' =Q -$n % $d := ⟨⟩
      return .isRat _ (Int.fract q) n' d q(isRat_intFract_of_isRat_negOfNat _ $n $d $h)
  | _, _, _ => failure

example : Int.fract (3.7 : ) = 0.7 := by norm_num
example : Int.fract (-3.7 : ) = 0.3 := by norm_num

end NormNum

example : ¬ IsIntegral  (1 / 2 : ) := by
  intro h
  obtain x, hx := ((isIntegrallyClosed_iff_isIntegrallyClosedIn ).1 inferInstance).isIntegral_iff.1 h
  apply_fun Int.fract at hx
  norm_num at hx

Qingfeng Li (Sep 17 2025 at 07:41):

Thanks, I leant a lot. Actrually I'm tring to prove some element is not integral, such as (√5 + 1) / 4 and find it hard to analyse the minpoly.
Is it easy to prove

import Mathlib
open Polynomial
example : ¬ IsIntegral  ((5 + 1) / 4 : ) := by
  let f : [X] := C 4 * X ^ 2 - C 2 * X - C 1
  have f_root : f.aeval ((5 + 1) / 4 : ) = 0 := by sorry
  sorry

by just judge that f is not monic? Or it need some works?

Riccardo Brasca (Sep 17 2025 at 08:16):

I think your problem is mathematical, not really Lean related. Can you write down a very precise proof (with pen and paper)? You find a non-monic poly that has the element as root, and then what?

Riccardo Brasca (Sep 17 2025 at 08:17):

Ruben Van de Velde said:

Shorter (*):

import Mathlib


section NormNum -- #26428
open Mathlib.Meta.NormNum Qq Int

variable {α : Type*} [Field α] [LinearOrder α] [IsStrictOrderedRing α] [FloorRing α]
variable {R : Type*} [Ring R] [LinearOrder R] [IsStrictOrderedRing R] [FloorRing R]
theorem isNat_intFract_of_isNat (r : R) (m : ) : IsNat r m  IsNat (Int.fract r) 0 := by
  rintro ⟨⟨⟩⟩; exact by simp

theorem isNat_intFract_of_isInt (r : R) (m : ) : IsInt r m  IsNat (Int.fract r) 0 := by
  rintro ⟨⟨⟩⟩; exact by simp

theorem isNNRat_intFract_of_isNNRat (r : α) (n d : ) :
    IsNNRat r n d  IsNNRat (Int.fract r) (n % d) d := by
  rintro inv, rfl
  refine inv, ?_⟩
  simp only [invOf_eq_inv,  div_eq_mul_inv, fract_div_natCast_eq_div_natCast_mod]

theorem isRat_intFract_of_isRat_negOfNat (r : α) (n d : ) :
    IsRat r (negOfNat n) d  IsRat (Int.fract r) (-n % d) d := by
  rintro inv, rfl
  refine inv, ?_⟩
  simp only [invOf_eq_inv,  div_eq_mul_inv, fract_div_intCast_eq_div_intCast_mod,
    negOfNat_eq, ofNat_eq_coe]

/-- `norm_num` extension for `Int.fract` -/
@[norm_num (Int.fract _)]
def evalIntFract : NormNumExt where eval {u α} e := do
  match e with
  | ~q(@Int.fract _ $instR $instO $instF $x) =>
    match  derive x with
    | .isBool .. => failure
    | .isNat _ _ pb => do
      let _i  synthInstanceQ q(IsStrictOrderedRing $α)
      assertInstancesCommute
      have z : Q() := Lean.mkRawNatLit 0
      letI : $z =Q 0 := ⟨⟩
      return .isNat _ z q(isNat_intFract_of_isNat $x _ $pb)
    | .isNegNat _ _ pb => do
      let _i  synthInstanceQ q(IsStrictOrderedRing $α)
      assertInstancesCommute
      have z : Q() := Lean.mkRawNatLit 0
      letI : $z =Q 0 := ⟨⟩
      return .isNat _ z q(isNat_intFract_of_isInt _ _ $pb)
    | .isNNRat _ q n d h => do
      let _i  synthInstanceQ q(Field $α)
      let _i  synthInstanceQ q(IsStrictOrderedRing $α)
      assertInstancesCommute
      have n' : Q() := Lean.mkRawNatLit (q.num.natAbs % q.den)
      letI : $n' =Q $n % $d := ⟨⟩
      return .isNNRat _ (Int.fract q) n' d q(isNNRat_intFract_of_isNNRat _ $n $d $h)
    | .isNegNNRat _ q n d h => do
      let _i  synthInstanceQ q(Field $α)
      let _i  synthInstanceQ q(IsStrictOrderedRing $α)
      assertInstancesCommute
      have n' : Q() := mkRawIntLit (q.num % q.den)
      letI : $n' =Q -$n % $d := ⟨⟩
      return .isRat _ (Int.fract q) n' d q(isRat_intFract_of_isRat_negOfNat _ $n $d $h)
  | _, _, _ => failure

example : Int.fract (3.7 : ) = 0.7 := by norm_num
example : Int.fract (-3.7 : ) = 0.3 := by norm_num

end NormNum

example : ¬ IsIntegral  (1 / 2 : ) := by
  intro h
  obtain x, hx := ((isIntegrallyClosed_iff_isIntegrallyClosedIn ).1 inferInstance).isIntegral_iff.1 h
  apply_fun Int.fract at hx
  norm_num at hx

I was too lazy to even complain that norm_num wasn't able to close the goal, and you made it working, amazing!

Ruben Van de Velde (Sep 17 2025 at 08:26):

Yeah, back in June :/

Kenny Lau (Sep 17 2025 at 09:33):

it seems like we want a theorem of the form "if x satisfies polynomial p with certain properties then x is not integral over something"

Qingfeng Li (Sep 17 2025 at 09:34):

image.png

Kenny Lau (Sep 17 2025 at 09:35):

we have Polynomial.IsPrimitive

Kenny Lau (Sep 17 2025 at 09:35):

but it doesn't seem like the theorem you quoted is available

Kenny Lau (Sep 17 2025 at 09:35):

if you're interested please prove it and PR to mathlib (and ping me)

Qingfeng Li (Sep 17 2025 at 09:39):

OK, I think this theorem is correct in math (although I haven't proven precisely)

Kenny Lau (Sep 17 2025 at 09:42):

it might be advisable to find a reference for it

Kenny Lau (Sep 17 2025 at 09:43):

note that it is false as stated (consider the polynomial -X)

Riccardo Brasca (Sep 17 2025 at 10:04):

It' enough to find an irreducible polynomial whose leading coefficient is not a unit and that has the element as root. This follows from minpoly.isIntegrallyClosed_dvd and minpoly.prime_of_isIntegrallyClosed

Riccardo Brasca (Sep 17 2025 at 10:08):

I mean irreducible over (or over any integrally closed ring). If the polynomial is moreover primitive than, by Gauss lemma, it is enough to check irreducibility over .

Qingfeng Li (Sep 17 2025 at 10:36):

Thanks a lot! I finally solved my problem by this lemma.

import Mathlib

open Polynomial

lemma isIntegral_iff_leadingCoeff_of_irreducible_poly_isunit {R S : Type}
    [CommRing R] [IsDomain R] [IsIntegrallyClosed R] [CommRing S] [IsDomain S] [Algebra R S] [NoZeroSMulDivisors R S]
    {α : S} {f : R[X]} (f_irr : Irreducible f) (f_root : f.aeval α = 0) :
    IsIntegral R α  IsUnit f.leadingCoeff  := by
  constructor
  · intro int_a
    obtain g, hg := minpoly.isIntegrallyClosed_dvd int_a f_root
    have := Irreducible.isUnit_or_isUnit f_irr hg
    simp only [minpoly.not_isUnit R α, false_or] at this
    obtain r, uni_r, geq := Polynomial.isUnit_iff.mp this
    apply_fun Polynomial.leadingCoeff at hg
    rw [leadingCoeff_mul,  geq, leadingCoeff_C, minpoly.monic int_a, one_mul] at hg
    rw [hg]; exact uni_r
  · rintro f_uni
    obtain r, hr, _⟩ := (isUnit_iff_exists.mp f_uni)
    refine f * C r, monic_mul_C_of_leadingCoeff_mul_eq_one hr, ?_⟩
    rw [eval₂_mul, mul_eq_zero]; left
    exact f_root


lemma isIntegral_iff_leadingCoeff_of_primitive_and_map_irreducible_poly_isunit {R S K : Type}
    [CommRing R] [IsDomain R] [IsIntegrallyClosed R] [CommRing S] [IsDomain S] [Algebra R S] [NoZeroSMulDivisors R S]
    [Field K] [Algebra R K] [IsFractionRing R K] [NormalizedGCDMonoid R]
    {α : S} {f : R[X]} (f_pri : IsPrimitive f) (f_irr : Irreducible (map (algebraMap R K) f))
    (f_root : f.aeval α = 0) : IsIntegral R α  IsUnit f.leadingCoeff :=
    isIntegral_iff_leadingCoeff_of_irreducible_poly_isunit
    ((IsPrimitive.irreducible_iff_irreducible_map_fraction_map f_pri).mpr f_irr) f_root

Kenny Lau (Sep 17 2025 at 10:44):

@Qingfeng Li nice! would you like to PR?

Riccardo Brasca (Sep 17 2025 at 11:06):

Note that this has nothing to do with number fields: you should replace by any integrally closed domain and K by any L-algebra, where L satisfies IsFractionRing R L.

Qingfeng Li (Sep 17 2025 at 11:09):

Yes, I'll make my code more general and submit a PR soon

Riccardo Brasca (Sep 17 2025 at 11:12):

Also, please add the version for primitive polynomials and irreducibility over the fraction field, in practice this is what one does.

Kenny Lau (Sep 23 2025 at 13:31):

@Qingfeng Li I've added a comment to your PR

Riccardo Brasca (Sep 23 2025 at 14:08):

Feel free to ask my review (I will have time in 48 hours though)

Snir Broshi (Sep 28 2025 at 12:09):

Riccardo Brasca said:

Also, please add the version for primitive polynomials and irreducibility over the fraction field, in practice this is what one does.

Is the plan to add this in a separate PR? (separate from #29798)


Last updated: Dec 20 2025 at 21:32 UTC