Zulip Chat Archive

Stream: new members

Topic: How to use Fin n?


George Tsoukalas (Mar 09 2024 at 17:13):

Hi, I am trying to write in Lean a statement like the following:

section
variable (n : )
example (f : Fin n  ) (h :  k, f k  0) :  i : Fin n, f i  0 := sorry

#eval  i : Fin 5, i

While this doesn't throw any errors, the #eval line outputs 2, not 10. I am not sure how to interpret this - is i : Fin 4 a single element drawn from Fin 4? For this reason I am not sure if I can reason about the goal to prove correctly. Also, in the proof of the example I can write

example (f : Fin n  ) (h :  k, f k  0) :  i : Fin n, f i  0 := by
  have h' := h 3

which returns the message "failed to synthesize instance OfNat (Fin n) 3". I also tried replacing Fin with Finset.range , in which case the evaluation of the sum

#eval  i in Finset.range 5, i

returns 10, the correct value, but

example (f : Finset.range n  ) (h :  k, f k  0) :  i in Finset.range n, f i  0 := sorry

complains that "application type mismatch f i argument i has type \N : Type but is expected to have type { x // x ∈ range n } : Type. Does anyone know what the correct way to do this is? It's not just about computing the sum but also indexing a finite set of elements, in this case annotated via f.

Sophie Morel (Mar 09 2024 at 17:23):

The inhabitants of Fin n are not just the integers from 0 to n-1, they are couples formed by an integers i and a proof that i is less than n.
So for example, you'll get the correct sum if you write:

#eval  i : Fin 5, i.1

Sophie Morel (Mar 09 2024 at 17:24):

In your second example, you cannot apply f to 3 because 3 is not of type Fin n, it is of type Nat.

Sophie Morel (Mar 09 2024 at 17:28):

variable (n : )

open BigOperators in
example (f : Fin n  ) (h :  k, f k  0) :  i : Fin n, f i  0 := by
  rw [ Nat.pos_iff_ne_zero]
  apply Finset.sum_pos (fun k _  Nat.pos_iff_ne_zero.mpr (h k))
  -- Here to conclude we need `Fin n` to be nonempty, hence `n` to be positive.

Eric Wieser (Mar 09 2024 at 17:28):

Another spelling you can use is #eval ∑ i : Fin 5, (i : ℕ)

Sophie Morel (Mar 09 2024 at 17:29):

To finish the example:

open BigOperators in
example (f : Fin n  ) (h :  k, f k  0) (hn : n > 0) :  i : Fin n, f i  0 := by
  rw [ Nat.pos_iff_ne_zero]
  apply Finset.sum_pos (fun k _  Nat.pos_iff_ne_zero.mpr (h k))
  existsi 0, hn

Sophie Morel (Mar 09 2024 at 17:30):

The last line proves that Finset.univ of Fin n is nonempty by providing an element. Note how I had to write the element as a couple with entries 0 and the proof that 0 < n.

George Tsoukalas (Mar 09 2024 at 17:45):

Sophie Morel said:

variable (n : )

open BigOperators in
example (f : Fin n  ) (h :  k, f k  0) :  i : Fin n, f i  0 := by
  rw [ Nat.pos_iff_ne_zero]
  apply Finset.sum_pos (fun k _  Nat.pos_iff_ne_zero.mpr (h k))
  -- Here to conclude we need `Fin n` to be nonempty, hence `n` to be positive.

Makes sense. Is it generally most natural to use Fin for these kinds of formalizations?

Sophie Morel (Mar 09 2024 at 17:47):

I'm not sure I'm an expert, but I would say that it depends a lot on the context anyway (like where your function f comes from, and how you will use the positivity of the sum).

Sophie Morel (Mar 09 2024 at 17:49):

By the way, you got the unexpected #eval results because Fin n also has an addition, but it's addition mod n. That is what your #eval lines were calculating.

Yaël Dillies (Mar 09 2024 at 17:53):

Usually it's better to have f : ℕ → something, h : ∀ k < n, something_else (f k) and ∑ k in Finset.range n, f k

George Tsoukalas (Mar 09 2024 at 17:54):

Sophie Morel said:

By the way, you got the unexpected #eval results because Fin n also has an addition, but it's addition mod n. That is what your #eval lines were calculating.

Ah, that makes a lot of sense! Thank you!

George Tsoukalas (Mar 09 2024 at 17:56):

Yaël Dillies said:

Usually it's better to have f : ℕ → something, h : ∀ k < n, something_else (f k) and ∑ k in Finset.range n, f k

I was concerned about doing something like this because I am not sure how automation like aesop or duper might handle working in a "larger" space if they are converting the statement to something an SMT solver can digest. Do you happen to know if that a reasonable concern?

Yaël Dillies (Mar 09 2024 at 18:00):

aesop currently is rubbish at handling quantifiers (universal quantifiers in hypotheses and existential quantifiers in the goal), so I don't think that's much of a concern


Last updated: May 02 2025 at 03:31 UTC