Skip to content

feat(Data/Finset/Card): of cardinality between#20433

Closed
madvorak wants to merge 4 commits intomasterfrom
finset-of-card-between
Closed

feat(Data/Finset/Card): of cardinality between#20433
madvorak wants to merge 4 commits intomasterfrom
finset-of-card-between

Conversation

@madvorak
Copy link
Copy Markdown
Collaborator

@madvorak madvorak commented Jan 3, 2025


Open in Gitpod

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jan 3, 2025

PR summary 61b2a51af5

Import changes for modified files

No significant changes to the import graph

Import changes for all files
Files Import difference

Declarations diff

+ of_cardinality_between_of_disjoint

You can run this locally as follows
## summary with just the declaration names:
./scripts/declarations_diff.sh <optional_commit>

## more verbose report:
./scripts/declarations_diff.sh long <optional_commit>

The doc-module for script/declarations_diff.sh contains some details about this script.


No changes to technical debt.

You can run this locally as

./scripts/technical-debt-metrics.sh pr_summary
  • The relative value is the weighted sum of the differences with weight given by the inverse of the current value of the statistic.
  • The absolute value is the relative value divided by the total sum of the inverses of the current values (i.e. the weighted average of the differences).

@github-actions github-actions Bot added the t-data Data (lists, quotients, numbers, etc) label Jan 3, 2025
Comment thread Mathlib/Data/Finset/Card.lean Outdated
madvorak and others added 3 commits January 3, 2025 14:09
Comment on lines +582 to +583
lemma of_cardinality_between_of_disjoint (hs : #s < n) (hn : n ≤ #s + #t) (hst : Disjoint s t) :
∃ (x : Finset α) (hxs : Disjoint x s), #(x.disjUnion s hxs) = n ∧ Nonempty x := by
Copy link
Copy Markdown
Contributor

@alreadydone alreadydone Jan 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should be satisfied with this statement:

Suggested change
lemma of_cardinality_between_of_disjoint (hs : #s < n) (hn : n ≤ #s + #t) (hst : Disjoint s t) :
∃ (x : Finset α) (hxs : Disjoint x s), #(x.disjUnion s hxs) = n ∧ Nonempty x := by
lemma of_cardinality_between_of_disjoint (hs : #s n) (hn : n ≤ #s + #t) (hst : Disjoint s t) :
∃ (x : Finset α) (hxs : Disjoint x s), #(x.disjUnion s hxs) = n := by

because nonemptiness can be easily deduced from this:

import Mathlib
open Finset in
example {n} {α} (s x : Finset α) (hxs : Disjoint x s) (eq : #(x.disjUnion s hxs) = n)
    (lt : #s < n) : x ≠ ∅ := by
  rintro rfl; rw [← eq] at lt; simp at lt

(Note I've replaced Nonempty x with x ≠ ∅.)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the purposes of #19607 I prefer the stronger version.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to have both lemmas?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes please; and please use the x ≠ ∅ statement: from the lemmas around Finset.nonempty_iff_ne_empty I think statements involving ∅ are considered the normal form.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pinging @YaelDillies for a second opinion on whether that or Nonempty is preferred.

@alreadydone alreadydone added the awaiting-author A reviewer has asked the author a question or requested changes. label Jan 3, 2025
@madvorak madvorak added awaiting-author A reviewer has asked the author a question or requested changes. and removed awaiting-author A reviewer has asked the author a question or requested changes. labels Jan 3, 2025
@YaelDillies
Copy link
Copy Markdown
Contributor

I don't really see the point of this lemma. Why can't you directly use Finset.exists_subset_card_eq? Your new lemma isn't (yet) used in #19607, so I can't really offer you a more precise replacement for it.

@madvorak
Copy link
Copy Markdown
Collaborator Author

madvorak commented Jan 6, 2025

I don't really see the point of this lemma. Why can't you directly use Finset.exists_subset_card_eq? Your new lemma isn't (yet) used in #19607, so I can't really offer you a more precise replacement for it.

You are right I don't use the new lemma. The lemma I use at the moment is:

import Mathlib.Tactic

lemma finset_of_cardinality_between {α β : Type*} [Fintype α] [Fintype β] {n : ℕ}
    (hα : Fintype.card α < n) (hn : n ≤ Fintype.card α + Fintype.card β) :
    ∃ b : Finset β, Fintype.card (α ⊕ b) = n ∧ Nonempty b := by
  have beta' : n - Fintype.card α ≤ Fintype.card β
  · omega
  obtain ⟨s, hs⟩ : ∃ s : Finset β, s.card = n - Fintype.card α :=
    (Finset.exists_subset_card_eq beta').imp (by simp)
  use s
  rw [Fintype.card_sum, Fintype.card_coe, hs]
  constructor
  · omega
  · by_contra ifempty
    have : s.card = 0
    · rw [Finset.card_eq_zero]
      rw [nonempty_subtype, not_exists] at ifempty
      exact Finset.eq_empty_of_forall_not_mem ifempty
    omega

It will probably change after the refactor suggested by Kevin Buzzard.

@madvorak
Copy link
Copy Markdown
Collaborator Author

madvorak commented Jan 6, 2025

Can you @YaelDillies nevertheless clarify whether Nonempty x or x ≠ ∅ is preferred?

@madvorak madvorak added WIP Work in progress and removed awaiting-author A reviewer has asked the author a question or requested changes. labels Jan 6, 2025
@YaelDillies
Copy link
Copy Markdown
Contributor

I don't use the new lemma. The lemma I use at the moment is: [...]. It will probably change after the refactor suggested by Kevin Buzzard.

Ah okay, then I suggest we leave that PR unmerged for the time being, until what you actually need becomes clearer

Can you @YaelDillies nevertheless clarify whether Nonempty x or x ≠ ∅ is preferred?

x.Nonempty is preferred

@madvorak
Copy link
Copy Markdown
Collaborator Author

madvorak commented Jan 6, 2025

Yes. All four PRs are labelled as WIP now.

@madvorak
Copy link
Copy Markdown
Collaborator Author

In the end, I will need exactly this lemma:

lemma finset_of_cardinality_between {α β : Type*} [Fintype α] [Fintype β] {n : ℕ}
    (hα : Fintype.card α < n) (hn : n ≤ Fintype.card α + Fintype.card β) :
    ∃ b : Finset β, Fintype.card (α ⊕ b) = n ∧ Nonempty b := by
  have beta' : n - Fintype.card α ≤ Fintype.card β
  · omega
  obtain ⟨s, hs⟩ : ∃ s : Finset β, s.card = n - Fintype.card α :=
    (Finset.exists_subset_card_eq beta').imp (by simp)
  use s
  rw [Fintype.card_sum, Fintype.card_coe, hs]
  constructor
  · omega
  · by_contra ifempty
    have : s.card = 0
    · rw [Finset.card_eq_zero]
      rw [nonempty_subtype, not_exists] at ifempty
      exact Finset.eq_empty_of_forall_not_mem ifempty
    omega

Do you @YaelDillies want to weigh in on how it should be generalized for Mathlib? Finset version perhaps?

@YaelDillies
Copy link
Copy Markdown
Contributor

This lemma is overly specific, I find, so I think you should inline it where needed.

Here's a golf, using new machinery that could belong in mathlib:

import Mathlib.Data.Fintype.Sum

namespace Equiv
variable {α β : Type*}

-- Analogue of `Equiv.optionIsSomeEquiv`
@[simps]
def sumIsLeft : {x : α ⊕ β // x.isLeft} ≃ α where
  toFun x := x.1.getLeft x.2
  invFun a := ⟨.inl a, Sum.isLeft_inl⟩
  left_inv | ⟨.inl _a, _⟩ => rfl
  right_inv _a := rfl

@[simps]
def sumIsRight : {x : α ⊕ β // x.isRight} ≃ β where
  toFun x := x.1.getRight x.2
  invFun b := ⟨.inr b, Sum.isRight_inr⟩
  left_inv | ⟨.inr _b, _⟩ => rfl
  right_inv _b := rfl

end Equiv

namespace Finset
variable {α β : Type*} {s : Finset (α ⊕ β)} {a : α} {b : β}

def left (s : Finset (α ⊕ β)) : Finset α := (s.subtype _).map Equiv.sumIsLeft.toEmbedding
def right (s : Finset (α ⊕ β)) : Finset β := (s.subtype _).map Equiv.sumIsRight.toEmbedding

@[simp] lemma mem_left : a ∈ s.left ↔ .inl a ∈ s := by simp [left]
@[simp] lemma mem_right : b ∈ s.right ↔ .inr b ∈ s := by simp [right]

lemma disjSum_left_right (s : Finset (α ⊕ β)) : s.left.disjSum s.right = s := by
  ext (a | b) <;> simp

lemma card_left_add_card_right (s : Finset (α ⊕ β)) : #s.left + #s.right = #s := by
  simpa using congr(#$s.disjSum_left_right)

@[simp] lemma left_eq_univ [Fintype α] : s.left = univ ↔ univ.disjSum ∅ ⊆ s := by
  simp [eq_univ_iff_forall, subset_iff]

@[simp] lemma right_eq_empty [Fintype α] : s.right = ∅ ↔ s ⊆ univ.disjSum ∅ := by
  simp [eq_empty_iff_forall_not_mem, subset_iff]

end Finset

open Finset

lemma Finset.of_cardinality_between {α β : Type*} [Fintype α] [Fintype β] {n : ℕ}
    (hα : Fintype.card α < n) (hn : n ≤ Fintype.card α + Fintype.card β) :
    ∃ s : Finset β, Fintype.card α + #s = n ∧ s.Nonempty := by
  obtain ⟨s, hs, -, rfl⟩ : ∃ s : Finset (α ⊕ β), _ :=
    exists_subsuperset_card_eq (subset_univ <| univ.disjSum ∅) (by simpa using hα.le)
      (by simpa using hn)
  refine ⟨s.right, by simpa [left_eq_univ.2 hs] using s.card_left_add_card_right, ?_⟩
  simp only [nonempty_iff_ne_empty, ne_eq, right_eq_empty, disjSum_empty]
  exact fun h ↦ hα.not_le <| by simpa using card_le_card h

@madvorak
Copy link
Copy Markdown
Collaborator Author

Interesting.

@leanprover-community-bot-assistant leanprover-community-bot-assistant added the merge-conflict The PR has a merge conflict with master, and needs manual merging. (this label is managed by a bot) label Feb 1, 2025
@madvorak madvorak closed this Feb 17, 2025
@YaelDillies
Copy link
Copy Markdown
Contributor

@madvorak, turns out my "new machinery that could belong in mathlib" was added to mathlib in #17014 by @b-mehta.

YaelDillies added a commit that referenced this pull request Mar 17, 2025
As a bonus, this lets us reduce imports. Also add the API that I independently came up with in #20433 (comment).
@YaelDillies
Copy link
Copy Markdown
Contributor

See also #23020

YaelDillies added a commit that referenced this pull request Mar 19, 2025
As a bonus, this lets us reduce imports. Also add the API that I independently came up with in #20433 (comment).
mathlib-bors Bot pushed a commit that referenced this pull request Mar 31, 2025
Add the API that I independently came up with in #20433 (comment).
@YaelDillies YaelDillies deleted the finset-of-card-between branch August 17, 2025 11:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-conflict The PR has a merge conflict with master, and needs manual merging. (this label is managed by a bot) t-data Data (lists, quotients, numbers, etc) WIP Work in progress

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants