Zulip Chat Archive

Stream: new members

Topic: Counting Ways to Choose


Nathan (Nov 03 2025 at 18:14):

I want to state this problem in lean:

657746365446619146.png

Is this a good way to do it?

import Mathlib.Data.Int.Init
import Mathlib.Data.Set.Card
import Mathlib.Order.Interval.Set.Defs

def B := Set.Icc (-100) 100
def S := {p : Set  |  a b : , p = {a, b}  a  b  a  B  b  B  a + b > a * b}

theorem POTD2415 : S.encard = 10199 := sorry

Ruben Van de Velde (Nov 03 2025 at 18:19):

It might be easier to work with \Z \times \Z, but I guess there's a question whether 1,100 and 100,1 are different solutions

Nathan (Nov 03 2025 at 18:19):

they're the same solution

Nathan (Nov 03 2025 at 18:19):

i started doing the proof with ZxZ before i realized that

Robin Arnez (Nov 03 2025 at 18:21):

What about docs#Sym2​?

Robin Arnez (Nov 03 2025 at 18:21):

(i.e. the type of unordered pairs)

Nathan (Nov 03 2025 at 18:23):

oh interesting

Nathan (Nov 03 2025 at 18:23):

thanks :pray:

Axel Boldt (Nov 03 2025 at 20:37):

But Sym2 will also include {a,a}, which you don't want.

Robin Arnez (Nov 03 2025 at 20:41):

Well, you can always use docs#Sym2.IsDiag

Kevin Buzzard (Nov 03 2025 at 21:01):

At this point I'm wondering whether it's just easiest to demand 100a<b100-100\leq a<b\leq 100 and have done with it; otherwise you'll just end up with several lines of boilerplate reducing you to this case at the beginning of the proof, which is enough to put people off. Clearly this rephrasing is equivalent.

Nathan (Nov 05 2025 at 18:22):

but i'm interested in using lean to prove that they're equivalent

Kevin Buzzard (Nov 05 2025 at 18:32):

I would say that the informal question itself is ambiguous. It's not clear to me that choosing (-1,2) is the same as, or different to, choosing (2,-1). I don't think you can argue that it's clear from the wording because I claim that "In how many ways can we choose two different integers between -100 and 100 inclusive such that the first is less than the second" is also a perfectly reasonable English statement, and would be interpreted as unordered pairs because of what happens next in the sentence. So one could even argue that sticking as closely as possible to the informal statement is impossible because you'd have to write an ambiguous formal statement, which isn't possible ;-)

However, if you are convinced that you know what the informal statement means, and that it means "unordered pair", then one way to proceed would be
(1) use docs#Sym2 and docs#Sym2.IsDiag in the statement
(2) decide how you're going to formalize the proof (e.g. perhaps you want to count 100a<b100-100\leq a<b\leq 100 in practice)
(3) prove an auxiliary lemma saying that there's a bijection between the contorted set that you want to work with and the ordered pairs which I'm suggesting
(4) start the proof of your contorted statement by rewriting to make it into the formally nice statement.

Vlad (Nov 06 2025 at 14:58):

An easy way to express the statement is to use a list and an easy way to prove it is to use native_decide:

def xs : List ( × ) := do
  let range := List.range 201 |>.map (· - (100 : ))
  let a  range; let b  range
  guard $ a < b  a * b < a + b
  return (a, b)

example : xs.length = 10199 := by
  native_decide

Kenny Lau (Nov 06 2025 at 15:00):

you should not use native_decide

Vlad (Nov 06 2025 at 15:08):

Proving that this formulation is equivalent to the set-theoretic approach is more involved:

Proof

Vlad (Nov 06 2025 at 15:08):

you should not use native_decide

The documentation is clear regarding what native_decide does. It is left to the users to decide to what extent they trust lean compiler in addition to the kernel.

Alfredo Moreira-Rosa (Nov 06 2025 at 16:25):

I think Kenny meant, you should not use native_decide if you want to integrate your work to mathlib. Plus be aware that native_decide, since it's not checked by the kernel, that it's not considered to be a valid formal proof.

Kenny Lau (Nov 07 2025 at 01:57):

def f := false

@[implemented_by f]
def g := true

example : False :=
  have h₁ : g = true := rfl
  have h₂ : g = false := by native_decide
  absurd (h₁.symm.trans h₂) (by decide)

Last updated: Dec 20 2025 at 21:32 UTC