Zulip Chat Archive

Stream: Is there code for X?

Topic: Real.isInteger


Jakob von Raumer (Jan 23 2025 at 08:58):

Is there a definition of what it means for a real number to be an integer (i.e. it's in the image of the cast)

Eric Wieser (Jan 23 2025 at 09:01):

Membership in Set.range Int.cast, or Int.castRingHom.range?

Kevin Buzzard (Jan 23 2025 at 09:11):

We also don't seem to have a bespoke definition of what it means for a real number to be rational, which surprised me recently.

Jakob von Raumer (Jan 23 2025 at 09:15):

Eric Wieser said:

Membership in Set.range Int.cast, or Int.castRingHom.range?

Yes, I just thought there would be enough need for an abbreviation (I was looking for a characterization of x+x\lfloor x \rfloor + \lceil x \rceil and was suprised that it didn't exist)

Jireh Loreaux (Jan 23 2025 at 12:58):

I wouldn't define it only for real numbers. Do it for any type with the cast.

Jakob von Raumer (Jan 23 2025 at 13:00):

With then giving the type explicitly?

Aaron Liu (Jan 23 2025 at 13:06):

Kevin Buzzard said:

We also don't seem to have a bespoke definition of what it means for a real number to be rational, which surprised me recently.

In Mathlib.Data.Real.Irrational, it's spelled as ¬Irrational :)

Jakob von Raumer (Jan 23 2025 at 14:05):

Jireh Loreaux said:

I wouldn't define it only for real numbers. Do it for any type with the cast.

What would you call it?

Jakob von Raumer (Jan 23 2025 at 14:44):

I think it would be really useful to have Real.IsInteger as a type class and equip it with all the closure properties... Does anyone know why Irrational hasn't been made a class (but instead simplifies composite terms)?

Yaël Dillies (Jan 23 2025 at 14:46):

What would you do with this typeclass?

Riccardo Brasca (Jan 23 2025 at 14:47):

A class is useful when there are instances for it. In this case it seems rather unlikely to have such instances. The same is true, for example, for Nat.Prime.

Jakob von Raumer (Jan 23 2025 at 14:49):

Have instances for all OfNats, for all casts from Int and Nat, and closure under addition, subtraction, multiplication, exponentiation

Jakob von Raumer (Jan 23 2025 at 14:50):

Guess the point against it would be that it's better style to norm_cast for those expressions

Eric Wieser (Jan 23 2025 at 15:07):

Jakob von Raumer said:

Have instances for all OfNats, for all casts from Int and Nat, and closure under addition, subtraction, multiplication, exponentiation

You get this closure for free with \mem Rat.castHom.range

Jakob von Raumer (Jan 23 2025 at 15:14):

What do you mean by "for free"? Composite expressions don't simplify

Eric Wieser (Jan 23 2025 at 15:18):

Jakob von Raumer said:

Have instances for all OfNats, for all casts from Int and Nat, and closure under addition, subtraction, multiplication, exponentiation

I think you're implying that "the property is structural" is a sufficient argument for using a typeclass, but I think the requirement is usually also that "the property is structural and about types"

Eric Wieser (Jan 23 2025 at 15:21):

(of course typeclasses do work in the former case, but I think it's controversial in the context of mathlib to use them in this way)

Jakob von Raumer (Jan 23 2025 at 15:30):

Yea I guess the point of reference is something like Subgroup.mul_mem or so

Jakob von Raumer (Jan 23 2025 at 15:30):

I just like the brevity of something like this

class Real.IsInteger (r : ) : Prop := sorry

instance [OfNat  n] : Real.IsInteger (OfNat.ofNat n : ) := sorry

@[simp]
lemma floor_isInteger {r : } [Real.IsInteger r] : r = r := sorry

example {r : } [Real.IsInteger r] : 5 + r = 5 + r := by simp

Jakob von Raumer (Jan 23 2025 at 15:34):

Ah, bad example, the OfNat is already pulled out by another simp lemma :sweat_smile:

Jakob von Raumer (Jan 23 2025 at 16:07):

NeZerowould be a similar thing

Yakov Pechersky (Jan 23 2025 at 16:35):

My thought is that in these "this prop is obvious for some subclass of terms of the type", this is the place for an autoparam with a possibly custom (simple) tactic.

Yakov Pechersky (Jan 23 2025 at 16:36):

In the case of this floor example, the stronger lemma is the iff. Which could then be used in the custom autoparam tactic to discharge the proof obligation.

Violeta Hernández (Jan 23 2025 at 17:45):

I think this might be somewhat of an XY. Given h : x \in range coe, you can use obtain <y, rfl> := h to rewrite any instance of x by ↑y, at which point you get all the structural lemmas you're talking about in the form of cast_add, cast_mul, etc.

Violeta Hernández (Jan 23 2025 at 17:47):

This approach works for casts from naturals, integers, and rationals, and requires none of the duplication.

Jireh Loreaux (Jan 24 2025 at 06:56):

Violeta, while I understand your point completely, I think it nevertheless makes sense to have the following (along with IsInteger and maybe IsRational versions, although I suspect IsRational will be much less useful than the others):

import Mathlib

variable {α : Type*}

def IsNatural [NatCast α]  (a : α) : Prop := a  Set.range (() :   α)

namespace IsNatural

@[simp]
protected lemma ofNat [NatCast α] (n : ) [n.AtLeastTwo] : IsNatural (ofNat(n) : α) := OfNat.ofNat n, rfl

section AddMonoidWithOne

variable [AddMonoidWithOne α]

@[simp]
protected lemma zero : IsNatural (0 : α) := 0, Nat.cast_zero

@[simp]
protected lemma one : IsNatural (1 : α) := 1, Nat.cast_one

@[aesop safe apply]
protected lemma add {n m : α} (hn : IsNatural n) (hm : IsNatural m) : IsNatural (n + m) := by
  obtain n, rfl := hn
  obtain m, rfl := hm
  exact n + m, Nat.cast_add _ _⟩

@[aesop safe apply]
protected lemma smul {n : } {m : α} (hm : IsNatural m) : IsNatural (n  m) := by
  induction n with
  | zero => simp
  | succ n ih =>
    rw [add_nsmul]
    aesop

end AddMonoidWithOne

section Semiring

variable [Semiring α]

@[aesop safe apply]
protected lemma mul {n m : α} (hn : IsNatural n) (hm : IsNatural m) : IsNatural (n * m) := by
  obtain n, rfl := hn
  obtain m, rfl := hm
  exact n * m, Nat.cast_mul _ _⟩

@[aesop safe apply]
protected lemma pow {n : } {m : α} (hm : IsNatural m) : IsNatural (m ^ n) := by
  obtain m, rfl := hm
  exact m ^ n, by simp

example {n m k : α} (hn : IsNatural n) (hm : IsNatural m) (hk : IsNatural k) :
    IsNatural (k ^ 2 + 3  n + k * m + 24 : α) := by
  aesop

end Semiring

end IsNatural

Others can feel free to disagree here. There are certainly other things that could be done. (e.g., you could show that k n m in the example are all in the range of cast interpreted as a ring hom, then you could probably prove also that the quantity contained therein is in that range using existing aesop lemmas.) But I still think this could be nice and perhaps worth having.

Jireh Loreaux (Jan 24 2025 at 07:00):

@Jakob von Raumer in the above, notice that there is no need for type classes or to provide the type explicitly.

Eric Wieser (Jan 24 2025 at 11:22):

I'll note we do have docs#Mathlib.Meta.NormNum.IsNat, though it's an implementation detail of norm_num

Jakob von Raumer (Jan 27 2025 at 09:38):

Thanks, it's a good alternative to (ab)using the type classes. Is there now a concerted effort to annotate more lemmas for aesop?

Kevin Buzzard (Jan 27 2025 at 10:20):

BTW one really silly thing in mathlib is docs#harmonic_not_int , which says that for n2n\geq2 we have i=1n1i∉Z\sum_{i=1}^n\frac{1}{i}\not\in\Z but it's spelt using docs#Rat.isInt which is Bool-valued so the statement looks really odd in the docs.

My earlier comment about "we don't have the predicate that a real number is rational" was misremembered on my part -- what I meant was "we don't seem to have the predicate that a rational number is integral".

Jireh Loreaux (Jan 27 2025 at 17:39):

I think you should annotate lemmas with aesop whenever it makes sense. We should certainly use it.


Last updated: May 02 2025 at 03:31 UTC