Zulip Chat Archive
Stream: new members
Topic: How to get a function from this existence theorem?
Juho Pitkänen (Oct 08 2025 at 13:29):
I recently proved the existence and unique of remainder and integer division. I was wondering whether it was possible to get a function for the remainder out of the existence theorem. The current issue is that the existence theorem requires the divisor to be positive, so a naïve approach with Nat.find isn't working. Perhaps the function should take the dividend, the divisor, and a proof that the divisor is positive? However, I have no idea of how to implement this, apart from having a divisor as well as a proof of a property of that divisor reminding me of the BKH interpretation of a proof for existential quantification.
By the way, my code is probably horribly inefficient. I intentionally tried to prove stuff manually, but I was wondering whether Mathlib already had similar stuff, and whether if I my proofs had redundant steps that could have been avoided by alterations to the strategy. Any feedback on the code itself would be appreciated too, even if it doesn't solve my question.
Kenny Lau (Oct 08 2025 at 13:29):
you can case on whether the divisor is 0
Kenny Lau (Oct 08 2025 at 13:30):
the syntax is if h : <condition> then f h else g h
Kenny Lau (Oct 08 2025 at 13:31):
Juho Pitkänen said:
horribly inefficient
as for efficiency, there's no point trying to optimise, because the Lean Nat secretly uses C (or whatever library) when doing computation
Juho Pitkänen (Oct 08 2025 at 13:32):
By efficiency, I was thinking about lines of code and effort required to prove something rather than performance
Kenny Lau (Oct 08 2025 at 13:33):
Juho Pitkänen said:
I was wondering whether Mathlib already had similar stuff
I assure you mathlib has everything you possibly need and want regarding integer division
Juho Pitkänen (Oct 08 2025 at 13:35):
Kenny Lau wrote:
the syntax is
if h : <condition> then f h else g h
Is there a way to use the proof the condition holds? I am unsure how I'd actually use this in the context of the file
Kenny Lau (Oct 08 2025 at 13:35):
that's the f h part, I used the same letter h to show you that.
Juho Pitkänen (Oct 08 2025 at 13:37):
I think I maybe understand. I need to review the manuals. Maybe this is covered in _Functional Programming in Lean_?
Juho Pitkänen (Oct 08 2025 at 13:38):
For clarity, this is the statement of existence I proved in the file provided
∀n m : Nat, m > 0 → ∃q r : Nat, n = q * m + r ∧ r < m
Robin Arnez (Oct 08 2025 at 16:27):
I guess if you want to know how to do it with existing library stuff:
example : ∀ n m : Nat, m > 0 → ∃ q r : Nat, n = q * m + r ∧ r < m := by
intro n m hm
exists n / m, n % m
rw [Nat.div_add_mod']
exact ⟨rfl, Nat.mod_lt n hm⟩
Juho Pitkänen (Oct 08 2025 at 16:32):
Thanks, @Robin Arnez . Is uniqueness similarly quick and provided for by mathlib?
Robin Arnez (Oct 08 2025 at 16:49):
A bit less quick but still:
example : ∀ n m qa qb ra rb : Nat, n = qa * m + ra ∧ ra < m → n = qb * m + rb ∧ rb < m → qa = qb ∧ ra = rb := by
intro n m
have helper (q r : Nat) : n = q * m + r → r < m → r = n % m ∧ q = n / m := by
rintro rfl hr
rw [Nat.mul_add_mod_self_right, Nat.mod_eq_of_lt hr, Nat.add_comm,
Nat.add_mul_div_right _ _ (Nat.zero_lt_of_lt hr), Nat.div_eq_of_lt hr, Nat.zero_add]
exact ⟨rfl, rfl⟩
intro qa qb ra rb ⟨h₁, h₂⟩ ⟨h₃, h₄⟩
simp [helper qa ra h₁ h₂, helper qb rb h₃ h₄]
Juho Pitkänen (Oct 08 2025 at 16:54):
I see, still quite elegant. Taught me a few useful tricks and developed my mental model
Kenny Lau (Oct 08 2025 at 17:00):
Kenny Lau (Oct 08 2025 at 17:01):
(as I said above, I assure you mathlib has everything you possibly need and want regarding integer division)
Kenny Lau (Oct 08 2025 at 17:01):
also you seem to use "integer" to mean natural numbers? that might be a bit confusing
Kenny Lau (Oct 08 2025 at 17:01):
in any case both statements are true, mathlib has anything you can ever want about Nat or Int division
Juho Pitkänen (Oct 08 2025 at 17:24):
Kenny Lau said:
also you seem to use "integer" to mean natural numbers? that might be a bit confusing
If I’ve said integer in this thread, I’ve meant the natural numbers
Juho Pitkänen (Oct 08 2025 at 19:02):
Kenny Lau said:
the syntax is
if h : <condition> then f h else g h
I tried the following, and I think the syntax is okay
if h : b > 0 then Nat.find (remainder_existence a b h) else a
However, I get the error
failed to synthesize
DecidablePred fun n ↦ ∃ r, a = n * b + r ∧ r < b
I think I know the reason, that being that Lean is unsure of how to decide this proposition. Seems like this is harder than I thought. Perhaps mathlib uses an inductive definition instead and then just proves properties about it?
Aaron Liu (Oct 08 2025 at 19:08):
can you write down a #mwe
Aaron Liu (Oct 08 2025 at 19:09):
I was not expecting this error
Aaron Liu (Oct 08 2025 at 19:09):
and I really don't see where it could be coming from
Aaron Liu (Oct 08 2025 at 19:09):
oh is it on the Nat.find
Juho Pitkänen (Oct 08 2025 at 19:10):
Aaron Liu kirjoitti:
oh is it on the
Nat.find
Indeed
Aaron Liu (Oct 08 2025 at 19:11):
then you may have luck swapping the existence statement around, to be ∃ r, r < b ∧ a = n * b + r instead of ∃ r, a = n * b + r ∧ r < b
Juho Pitkänen (Oct 08 2025 at 19:11):
Aaron Liu kirjoitti:
can you write down a #mwe
There's a link to the file I typed this in at the top. I imported Mathlib and proved the theorem remainder_existence : ∀n m : Nat, m > 0 → ∃q r : Nat, n = q * m + r ∧ r < m
Kenny Lau (Oct 08 2025 at 19:14):
@Juho Pitkänen indeed, mathlib knows that if the quantifier is bounded then you just need to search finitely many things, but the way to say the quantifier bounded is that it has to go on the front, meaning ∃ r, a = n * b + r ∧ r < b won't work but ∃ r, r < b ∧ a = n * b + r will
Kenny Lau (Oct 08 2025 at 19:15):
because Lean can't work based on intuition, it works based on very specific rules, and one of those rules is that it only looks at the form of your expression and doesn't try to guess the meaning, so it only knows about the bounded quantifier if you put it at the front
Juho Pitkänen (Oct 08 2025 at 19:15):
Ah, that makes sense.
Juho Pitkänen (Oct 08 2025 at 19:21):
theorem remex_alt : ∀n m : Nat, m > 0 → ∃q r : Nat, r < m ∧ n = q * m + r := by{
intro n m mpos
have remex := remainder_existence n m mpos
cases' remex with q qh
cases' qh with r remex
use q
use r
tauto
}
def natdiv := fun a b : Nat =>
if h : b > 0 then Nat.find (remex_alt a b h) else a
I got it to work, thanks to y'all's help.
Kenny Lau (Oct 08 2025 at 19:27):
btw in lean (3/0, 3%0) is (0, 3)
Juho Pitkänen (Oct 08 2025 at 19:27):
Ah, interesting
Juho Pitkänen (Oct 08 2025 at 19:28):
Actually, that makes far more sense than how I had defined it.
Juho Pitkänen (Oct 08 2025 at 19:29):
Looking at the way I proved Liu's alternative version of the theorem, it seems rather verbose, which could be a code smell. I initially assumed tauto would just solve it outright but apparently one has to get rid of the quantifiers first. Am I doing something wrong?
Kenny Lau (Oct 08 2025 at 19:30):
you mean the one where he swapped the order?
Aaron Liu (Oct 08 2025 at 19:30):
theorem remex_alt : ∀ n m : Nat, m > 0 → ∃ q r : Nat, r < m ∧ n = q * m + r := by
simpa only [and_comm] using remainder_existence
Aaron Liu (Oct 08 2025 at 19:31):
does that work
Juho Pitkänen (Oct 08 2025 at 19:31):
It does! Magical
Juho Pitkänen (Oct 08 2025 at 19:32):
Thanks for the help, both of you
Last updated: Dec 20 2025 at 21:32 UTC