Zulip Chat Archive

Stream: general

Topic: finite stuff


Patrick Massot (Apr 08 2020 at 10:58):

I'm really bad at manipulating finite sets in Lean. This is frustrating because everything about finite sets seem obvious. I'd be very grateful if someone could prove the following lemmas (the second one has the same assumption but a more precise conclusion):

import data.set.finite
open set

variables {ι : Type*} {α : Type*} {s : ι  set α} {t : set α}

lemma finite_stuff  (tfin : finite t) (h : t   i, s i) :
   I : finset ι, t   i  I, s i :=
sorry

lemma finite_stuff' (tfin : finite t) (h : t   i, s i) :
  I : finset ι,  σ : {i | i  I}  set α,
 ( i, finite (σ i))  ( i, σ i  s i)  t   i, σ i :=
sorry

Of course I'm also interested if someone explains those lemmas should be stated like this and will be a pain to use.

Johan Commelin (Apr 08 2020 at 11:09):

This reminds me of https://github.com/leanprover-community/mathlib/blob/51553e36ff9ae93ee4fbfb05a39e5d04c71be565/src/linear_algebra/finsupp.lean#L434

Johan Commelin (Apr 08 2020 at 11:13):

@Patrick Massot I think the statements are fine. (Maybe I would use t : finset _... To prove this, I would do something like

  have : \forall x : (t : Type*), \ex i, x \in s i,
  choose this using f hf,
  let I := finset.image f t,

modulo minor tweaks

Kevin Buzzard (Apr 08 2020 at 11:20):

apparently Lean can't synthesize decidable equality on iota. I am assuming that this isn't an issue for Patrick...

Kevin Buzzard (Apr 08 2020 at 11:23):

example (α : Type*) (t : set α) [finite t] : fintype t := by apply_instance -- fails

Mario Carneiro (Apr 08 2020 at 11:24):

I think you can do cases on the proof of finite t

Mario Carneiro (Apr 08 2020 at 11:25):

is finite even a typeclass?

Kevin Buzzard (Apr 08 2020 at 11:25):

no it isn't -- sorry. But still...

Mario Carneiro (Apr 08 2020 at 11:25):

yeah, it's defined as nonempty (fintype t) so just pop it open and use resetI

Kevin Buzzard (Apr 08 2020 at 11:26):

It's great that to prove this triviality I need to unfreeze local instances :-)

Mario Carneiro (Apr 08 2020 at 11:27):

hey, you're the one that wants to use instances that aren't present in the statement

Mario Carneiro (Apr 08 2020 at 11:27):

it's not needed for the statement and I'm not sure how it's being used in the proof

Kevin Buzzard (Apr 08 2020 at 11:29):

stupid mum_bUnion_iff wants the term to be in a set, not a finset :-)

Kevin Buzzard (Apr 08 2020 at 11:30):

How come mem_Union is an iff and mem_bUnion isn't?

Mario Carneiro (Apr 08 2020 at 11:33):

probably because mem_bUnion is too old

Kevin Buzzard (Apr 08 2020 at 11:33):

lemma finite_stuff  (tfin : finite t) (h : t   i, s i) :
   I : finset ι, t   i  I, s i :=
begin
  have :  x : t,  i, x.1  s i,
    rintros x, hx, rcases h hx with ⟨_, i, rfl, hi, exact i, hi,
  choose f hf using this,
  tactic.unfreeze_local_instances,
  cases tfin,
  use finset.image f finset.univ,
  intros x hx,
  rw mem_Union,
  use f x, hx,
  rw mem_Union,
  existsi _,
  apply hf,
  rw finset.mem_image,
  use x, hx, simp,
end

Kevin Buzzard (Apr 08 2020 at 11:33):

That bit at the end could use some tidying

Mario Carneiro (Apr 08 2020 at 11:34):

it looks like a term mode proof written vertically

Kevin Buzzard (Apr 08 2020 at 11:34):

that's how I roll

Kevin Buzzard (Apr 08 2020 at 11:34):

you should see my codewars solutions

Kevin Buzzard (Apr 08 2020 at 11:39):

@Patrick Massot in the second one, why not have sigma mapping to finset alpha? it's finset.unbind then :-)

Kevin Buzzard (Apr 08 2020 at 11:45):

Did someone find a proof of finite t -> finite s \cap t?

Kevin Buzzard (Apr 08 2020 at 11:48):

There should be a mem_fUnion

Kevin Buzzard (Apr 08 2020 at 11:48):

or possibly a mem_fUnion_iff...

Kevin Buzzard (Apr 08 2020 at 11:50):

lemma finite_stuff' (tfin : finite t) (h : t   i, s i) :
  I : finset ι,  σ : {i | i  I}  set α,
 ( i, finite (σ i))  ( i, σ i  s i)  t   i, σ i :=
begin
  cases finite_stuff tfin h with I hI,
  use I,
  use (λ x, s x.1  t),
  split,
  { intro i, sorry}, -- finite t → finite s ∩ t
  split,
  { intro i, apply inter_subset_left},
  { intros x hx,
    rw mem_Union,
    replace hI := hI hx,
    rw mem_Union at hI,
    cases hI with i hi,
    rw mem_Union at hi,
    cases hi with hi hsi,
    use i, hi,
    split,
      exact hsi,
    exact hx}
end

I'm not sure this is mathlib-ready </sarcasm>, and I assumed finite t -> finite s \cap t, but if it's just something you need now then there it is

Kevin Buzzard (Apr 08 2020 at 11:51):

I'm not sure these are term mode proofs really, because of the occasional rw mem_Union.

Kevin Buzzard (Apr 08 2020 at 11:52):

The proof of mem_Union doesn't seem to be rfl

Mario Carneiro (Apr 08 2020 at 12:33):

lemma finite_stuff' (tfin : finite t) (h : t   i, s i) :
  I : finset ι,  σ : (I:set ι)  set α,
 ( i, finite (σ i))  ( i, σ i  s i)  t   i, σ i :=
begin
  cases finite_stuff tfin h with I hI,
  use I,
  use (λ x, s x.1  t),
  split,
  { intro i,
    apply finite_subset tfin,
    apply inter_subset_right },
  split,
  { intro i, apply inter_subset_left },
  { intros x hx,
    rw mem_Union,
    replace hI := hI hx,
    rw mem_Union at hI,
    cases hI with i hi,
    rw mem_Union at hi,
    cases hi with hi hsi,
    use i, hi,
    split,
    { exact hsi },
    { exact hx } }
end

Patrick Massot (Apr 08 2020 at 12:36):

Than you very much Kevin and Mario!

Patrick Massot (Apr 08 2020 at 12:36):

Mario, do you think we are missing intermediate lemmas here? It looks like a very long proof for such an obvious fact.

Mario Carneiro (Apr 08 2020 at 12:45):

here's kevin's proof in term mode:

```lean
lemma finite_stuff' (tfin : finite t) (h : t   i, s i) :
  I : finset ι,  σ : (I:set ι)  set α,
 ( i, finite (σ i))  ( i, σ i  s i)  t   i, σ i :=
let I, hI := finite_stuff tfin h in
I, λ x, s x.1  t,
  λ i, finite_subset tfin (inter_subset_right _ _),
  λ i, inter_subset_left _ _,
  λ x hx, mem_Union.2 $
    let i, hi, hsi := mem_bUnion_iff.1 (hI hx) in
    ⟨⟨i, hi, hsi, hx⟩⟩

Kevin Buzzard (Apr 08 2020 at 12:45):

Nice :-)

Mario Carneiro (Apr 08 2020 at 12:46):

although I did swap in the use of mem_bUnion_iff

Kevin Buzzard (Apr 08 2020 at 12:47):

To do that I would have had to understand how supr was implemented and I couldn't be bothered to dig

Mario Carneiro (Apr 08 2020 at 12:47):

I don't think this is an unreasonably long proof, given the complexity of the statement itself. Once you set the logical manipulation aside the only actually interesting part is the last 3 lines of my version of the proof

Mario Carneiro (Apr 08 2020 at 12:48):

I ctrl-clicked on mem_bUnion and looked for neighbors

Mario Carneiro (Apr 08 2020 at 12:48):

it was two lemmas previous

Patrick Massot (Apr 08 2020 at 12:50):

Do you think we should keep both version finite_stuff and finite_stuff'?

Patrick Massot (Apr 08 2020 at 12:50):

(with better names of course)

Mario Carneiro (Apr 08 2020 at 12:51):

If you find it useful, I don't see why not

Mario Carneiro (Apr 08 2020 at 12:52):

I usually try to find an appropriate constructive analogue for these sorts of things, that is, a function with the stated properties, since existentials have to be unpacked and lack global coherence of choices

Patrick Massot (Apr 08 2020 at 12:53):

In my question the first lemma was really meant as training for the second one.

Patrick Massot (Apr 08 2020 at 12:53):

I want to use only the second one.

Patrick Massot (Apr 08 2020 at 12:54):

If you can turn this lemma into a function that would be even better of course.

Patrick Massot (Apr 08 2020 at 12:54):

(in order to avoid unpacking the existential)

Mario Carneiro (Apr 08 2020 at 12:55):

I feel like there is a simpler core underlying principle here

Patrick Massot (Apr 08 2020 at 12:55):

That was my question about missing lemmas.

Mario Carneiro (Apr 08 2020 at 12:56):

like, you can swap forall and exists a la skolemization for finite sets

Sebastien Gouezel (Apr 08 2020 at 12:58):

In the conclusion of finite_stuff', it would be better to replace t ⊆ ⋃ i, σ iwith t = ⋃ i, σ i.

Patrick Massot (Apr 08 2020 at 12:59):

I didn't need this, but feel free to prove that stronger version!

Mario Carneiro (Apr 08 2020 at 12:59):

what do you think of this formulation:

lemma finite_stuff'' (s : finset α) (P : α  ι  Prop)
  (h :  x  s,  i, P x i) :
   t : finset ι,  x  s,  i  t, P x i := sorry

Patrick Massot (Apr 08 2020 at 13:03):

That certainly looks cleaner. Can you prove it and deduce Sébastien's version of the original question?

Mario Carneiro (Apr 08 2020 at 13:04):

I think it's not quite enough to get the second version of the statement

Kevin Buzzard (Apr 08 2020 at 13:08):

Do we have an equiv e between finset X and Pi (s : set X), finite s, and the lemma that for x : X, x \in s iff x \in e s?

Mario Carneiro (Apr 08 2020 at 13:08):

Hey, isn't this just the collection principle from zfc?

Kevin Buzzard (Apr 08 2020 at 13:09):

All I know is that it's a mathematical triviality so it wouldn't surprise me if the logicians called it a principle

Mario Carneiro (Apr 08 2020 at 13:10):

I'm thinking of the version where you replace "finite" with "is a set" and depending on how you set things up it might be a theorem or an axiom

Kevin Buzzard (Apr 08 2020 at 13:10):

Like most principles

Mario Carneiro (Apr 08 2020 at 13:10):

it's essentially a souped up version of replacement without the assumption that the relation is a function

Kevin Buzzard (Apr 08 2020 at 13:11):

Replacement says the image of a set is a set

Mario Carneiro (Apr 08 2020 at 13:11):

right

Mario Carneiro (Apr 08 2020 at 13:11):

here it's the image under a relation

Kevin Buzzard (Apr 08 2020 at 13:11):

A relation on X

Mario Carneiro (Apr 08 2020 at 13:11):

and it's not really an image because you can take a subset

Mario Carneiro (Apr 08 2020 at 13:11):

but you have to preserve "enough" of the original relation

Kevin Buzzard (Apr 08 2020 at 13:14):

is_monoid_hom f is unbundled monoid homs and it's a class. monoid_hom is bundled and it's a structure

Kevin Buzzard (Apr 08 2020 at 13:15):

finite s is unbundled finiteness and it's a structure. finset is bundled and a structure

Patrick Massot (Apr 08 2020 at 13:15):

Do we have a version sInter s when s : finset (set X)? This is why I used finite everywhere instead of finset.

Kevin Buzzard (Apr 08 2020 at 13:15):

I mentioned fUnion earlier (which doesn't exist)

Patrick Massot (Apr 08 2020 at 13:15):

I know I can write ⋂₀ s.to_set but it looks silly.

Mario Carneiro (Apr 08 2020 at 13:16):

you can use the coercion as I did above

Mario Carneiro (Apr 08 2020 at 13:17):

If we did have something like that, I would prefer it generalize to lattices. I would call it finset.inf

Mario Carneiro (Apr 08 2020 at 13:18):

ok hey look what I found

Johan Commelin (Apr 08 2020 at 13:18):

Kevin Buzzard said:

finite s is unbundled finiteness and it's a structure. finset is bundled and a class

Whut?? Is finset a class?

Mario Carneiro (Apr 08 2020 at 13:18):

finset isn't a class

Johan Commelin (Apr 08 2020 at 13:18):

It should be just a structure, right?

Kevin Buzzard (Apr 08 2020 at 13:18):

Fixed

Kevin Buzzard (Apr 08 2020 at 13:18):

It's the wrong way around

Mario Carneiro (Apr 08 2020 at 13:20):

arguably, finite s should be called is_finite s. Is that your point?

Mario Carneiro (Apr 08 2020 at 13:21):

I think the problem, grammatically, is that finite is an adjective and monoid_hom is a noun

Kevin Buzzard (Apr 08 2020 at 13:22):

I am saying that the class/structure choice is different in the two situations for both the unbundled and the bundled concepts

Kevin Buzzard (Apr 08 2020 at 13:22):

I think I have this straight now

Mario Carneiro (Apr 08 2020 at 13:22):

Oh I see. Well, using typeclasses for these things has always been dubious, that's why we're moving away from them

Kevin Buzzard (Apr 08 2020 at 13:23):

I'm saying that either finset should be a structure or subgroup should be a class

Kevin Buzzard (Apr 08 2020 at 13:23):

Reasoning purely by analogy

Mario Carneiro (Apr 08 2020 at 13:23):

finset is a structure

Mario Carneiro (Apr 08 2020 at 13:23):

subgroup is also a structure

Kevin Buzzard (Apr 08 2020 at 13:24):

I see so I still have one error

Mario Carneiro (Apr 08 2020 at 13:24):

I'm failing to see past the typo to the point

Kevin Buzzard (Apr 08 2020 at 13:24):

Is finite a class?

Kevin Buzzard (Apr 08 2020 at 13:25):

I'm on mobile right now

Kevin Buzzard (Apr 08 2020 at 13:25):

Because is_subgroup is a class

Mario Carneiro (Apr 08 2020 at 13:26):

finite is not a class, is_subgroup is a class, and yes this is inconsistent

Mario Carneiro (Apr 08 2020 at 13:27):

my proposed solution is to delete is_subgroup and call it a day

Kevin Buzzard (Apr 08 2020 at 13:27):

Is finite deprecated? Because is_subgroup is, kinda

Mario Carneiro (Apr 08 2020 at 13:27):

finite is not deprecated, it is meant to be a proposition to talk about finiteness in other positions

Mario Carneiro (Apr 08 2020 at 13:28):

for example you can meaningfully negate it

Kevin Buzzard (Apr 08 2020 at 13:30):

This is some sort of indication that one should stick to finsets where one can though

Kevin Buzzard (Apr 08 2020 at 13:30):

Bundled ftw

Kevin Buzzard (Apr 08 2020 at 13:30):

We should have infinset

Reid Barton (Apr 08 2020 at 13:54):

import topology.subset_properties
import data.set.finite
open set

variables {ι : Type*} {α : Type*} {s : ι  set α} {t : set α}

lemma finite_stuff  (tfin : finite t) (h : t   i, s i) :
   I : finset ι, t   i  I, s i :=
begin
  letI : topological_space α := ,
  haveI : discrete_topology α := rfl,
  exact tfin.compact.elim_finite_subcover _ (λ i, is_open_discrete _) h
end

Johan Commelin (Apr 08 2020 at 13:58):

Brilliant hack!

Patrick Massot (Apr 08 2020 at 13:58):

Too bad this topology stuff come too late.

Patrick Massot (Apr 08 2020 at 13:59):

You still get the jury special honorary mention.

Patrick Massot (Apr 08 2020 at 14:00):

It's too late because I want to put this below order.filter.basic. But it's also good to see that the form of the statement is used elsewhere in mathlib.

Reid Barton (Apr 08 2020 at 14:05):

Yes, I expected it to be easy but I didn't realize it would be quite this easy.

Ryan Lahfa (Apr 08 2020 at 14:09):

Mario Carneiro said:

for example you can meaningfully negate it

BTW, is it normal that push_neg on not set.finite cannot rename it as set.infinite, I guess it has to do with simp (?) ?

Ryan Lahfa (Apr 08 2020 at 14:09):

(I had to do a rw set.infinite in order to get the nice infinite S rather than not set.finite S)

Mario Carneiro (Apr 08 2020 at 14:10):

push_neg needs explicit support for each of these things. Seems like a good PR

Ryan Lahfa (Apr 08 2020 at 14:11):

Mario Carneiro said:

push_neg needs explicit support for each of these things. Seems like a good PR

Sounds good, thanks

Patrick Massot (Apr 08 2020 at 14:16):

Yes, every end-game negation in push_neg is hardcoded.

Patrick Massot (Apr 09 2020 at 09:42):

Damn, I was trying to put this finite stuff in the proper place before PRing, and guess what? https://leanprover-community.github.io/mathlib_docs/data/set/finite.html#set.finite_subset_Union

Kenny Lau (Apr 09 2020 at 09:45):

Johan Commelin (Apr 09 2020 at 09:50):

So... why did library_search not find this?

Mario Carneiro (Apr 09 2020 at 09:52):

It's very unlikely that library_search will find longer statements, because the probability that you spell the theorem the same way as the library decreases exponentially with the length of the theorem

Mario Carneiro (Apr 09 2020 at 09:53):

Because of our rigid naming convention and fairly deterministic file organization it's much likely to notice a collision the way Patrick did, by putting it in its proper place and seeing something already there, or getting a name conflict with a duplicate of your theorem

Patrick Massot (Apr 09 2020 at 09:54):

Yes, I'm trying to fit in the more precise version, and it's a pain.

Patrick Massot (Apr 09 2020 at 09:54):

Because of mathematically empty differences between my statement and the one already in mathlib.

Mario Carneiro (Apr 09 2020 at 09:55):

this is also why I highly recommend looking at sources for relevant files as a theorem discovery strategy

Patrick Massot (Apr 03 2021 at 18:42):

Let's try that Zulip tactic. For our experts in finiteness:

lemma set.finite.fin_param {α : Type*} {s : set α} (h : finite s) :
   f : fin (h.to_finset.card)  α, injective f  range f = s :=
sorry

Johan Commelin (Apr 03 2021 at 18:59):

@Patrick Massot voila

open function

lemma set.finite.fin_param {α : Type*} {s : set α} (h : s.finite) :
   f : fin (h.to_finset.card)  α, injective f  set.range f = s :=
begin
  classical,
  unfreezingI { cases h },
  obtain e := fintype.equiv_fin s,
  have : fintype.card s = (finset.card $ set.finite.to_finset h⟩),
  { symmetry,
    refine finset.card_congr (λ a ha, a, _⟩) _ _ _,
    { simpa only [set.finite.mem_to_finset] using ha },
    { intros, exact finset.mem_univ _ },
    { intros a b ha hb H, simpa only [subtype.mk_eq_mk] using H },
    { rintro a, ha -, refine a, _, rfl⟩, simpa only [set.finite.mem_to_finset] using ha } },
  rw  this,
  refine λ x, e.symm x, subtype.coe_injective.comp e.symm.injective, _⟩,
  ext x,
  simp only [set.mem_range],
  split,
  { rintro i, rfl⟩, exact (e.symm i).2 },
  { intro h, refine e x, h⟩, _⟩, rw e.symm_apply_apply, refl }
end

Patrick Massot (Apr 03 2021 at 20:29):

Thanks Johan! This is much more complicated than what I hoped for :sad:

Patrick Massot (Apr 03 2021 at 21:00):

I massaged a bit into:

lemma set.finite.finset_card_eq_fintype_card {α : Type*} {s : set α} (h : finite s) :
  h.to_finset.card = @fintype.card s h.fintype:=
begin
  letI := h.fintype,
  refine finset.card_congr (λ a ha, a, _⟩) _ _ _,
  { simpa only [set.finite.mem_to_finset] using ha },
  { intros, exact finset.mem_univ _ },
  { intros a b ha hb H, simpa only [subtype.mk_eq_mk] using H },
  { rintro a, ha -, refine a, _, rfl⟩, simpa only [set.finite.mem_to_finset] using ha }
end

noncomputable
lemma set.finite.equiv_fin {α : Type*} {s : set α} (h : finite s) : s  fin h.to_finset.card :=
begin
  classical,
  rw h.finset_card_eq_fintype_card,
  letI := h.fintype,
  exact classical.some (fintype.equiv_fin s).exists_rep
end

lemma set.finite.fin_param {α : Type*} {s : set α} (h : finite s) :
   f : fin (h.to_finset.card)  α, injective f  range f = s :=
let e := h.equiv_fin in
λ x, e.symm x, subtype.coe_injective.comp e.symm.injective, by simp [e.symm.surjective.range_comp]⟩

lemma set.finite.fin_param' {α : Type*} {s : set α} (h : finite s) :
   (n : ) (f : fin n  α), injective f  range f = s :=
_, h.fin_param

Now I'm sure @Mario Carneiro will explain why we are writing nonsense.

Eric Wieser (Apr 03 2021 at 21:36):

noncomputable lemma strikes me as nonsense

Eric Wieser (Apr 03 2021 at 21:38):

Probably the conclusion should be nonempty (s \equiv fin _), which also eliminates the classical

Bhavik Mehta (Apr 03 2021 at 22:05):

Patrick Massot said:

Thanks Johan! This is much more complicated than what I hoped for :sad:

open_locale classical

lemma set.finite.fin_param' {α : Type*} {s : set α} (h : finite s) :
   (n : ) (f : fin n  α), injective f  range f = s :=
let f := (fintype.equiv_fin (h.to_finset : set α)).out in
_, coe  f.symm, subtype.coe_injective.comp (equiv.injective _),
 set.ext $ λ x, λ y, h⟩, by simpa [h] using (f.symm y).2, λ hs, f x, by simpa⟩, by simp⟩⟩⟩

Eric Wieser (Apr 04 2021 at 08:44):

Presumably you can avoid choice there by using docs#trunc.rec instead of trunc.out?

Eric Wieser (Apr 04 2021 at 08:45):

Or better, docs#nonempty_of_trunc

Patrick Massot (Apr 04 2021 at 16:35):

I don't see how any of this could avoid choice here.

Eric Wieser (Apr 04 2021 at 17:09):

Your conclusion is in prop, so you don't need to ever construct anything

Patrick Massot (Apr 04 2021 at 17:10):

Indeed, it's in prop

Eric Wieser (Apr 04 2021 at 17:22):

You're correct though, docs#fintype.equiv_fin already uses classical logic

Eric Wieser (Apr 04 2021 at 17:23):

Which seems ridiculous, because isn't the whole point of trunc to be a computable version of nonempty?

Patrick Massot (Apr 04 2021 at 17:23):

Yes, that's the issue. Maybe a proof exists in classical logic without going through that lemma, but I'm not very interested in avoiding classical logic anyway...

Eric Wieser (Apr 04 2021 at 17:24):

The docs specifically list that lemma as being computable

Eric Wieser (Apr 04 2021 at 17:24):

Oh, I guess functions can still be computable but use classical logic in internal proofs

Mario Carneiro (Apr 05 2021 at 05:03):

@Eric Wieser There is a difference between being computable and avoiding choice entirely. The former means that any uses of AC are confined to proof arguments where they don't hamper code generation. Large parts of mathlib are computable, but only a small fraction is AC-free

Mario Carneiro (Apr 05 2021 at 05:08):

In principle most of the things that are computable are also AC-free, but there aren't too many people besides me making any attempt to actually make it happen, and there are several foundational bits that need adjustment before there is any hope of making, say, finsets AC-free. I made another push toward AC-freedom in lean core recently, so we should see some improvement in mathlib when the next minor version is released.


Last updated: Dec 20 2023 at 11:08 UTC