Finite sets
mathlib has several different models for finite sets, and it can be confusing when you're first getting used to them!
This file builds the basic theory of finset α
,
modelled as a multiset α
without duplicates.
It's "constructive" in the since that there is an underlying list of elements, although this is wrapped in a quotient by permutations, so anytime you actually use this list you're obligated to show you didn't depend on the ordering.
There's also the typeclass fintype α
(which asserts that there is some finset α
containing every term of type α
)
as well as the predicate finite
on s : set α
(which asserts nonempty (fintype s)
).
Equations
- finset.has_decidable_eq s₁ s₂ = decidable_of_iff (s₁.val = s₂.val) finset.val_inj
Equations
set coercion
Equations
extensionality
subset
Equations
- finset.partial_order = {le := has_subset.subset finset.has_subset, lt := has_ssubset.ssubset finset.has_ssubset, le_refl := _, le_trans := _, lt_iff_le_not_le := _, le_antisymm := _}
Nonempty
The property s.nonempty
expresses the fact that the finset s
is not empty. It should be used
in theorem assumptions instead of ∃ x, x ∈ s
or s ≠ ∅
as it gives access to a nice API thanks
to the dot notation.
empty
The empty finset
Equations
- finset.empty = {val := 0, nodup := _}
Equations
Equations
- finset.inhabited = {default := ∅}
singleton
{a} : finset a
is the set {a}
containing a
and nothing else.
This differs from insert a ∅
in that it does not require a decidable_eq
instance for α
.
cons
cons a s h
is the set {a} ∪ s
containing a
and the elements of s
. It is the same as
insert a s
when it is defined, but unlike insert a s
it does not require decidable_eq α
,
and the union is guaranteed to be disjoint.
disjoint union
disj_union s t h
is the set such that a ∈ disj_union s t h
iff a ∈ s
or a ∈ t
.
It is the same as s ∪ t
, but it does not require decidable equality on the type. The hypothesis
ensures that the sets are disjoint.
insert
insert a s
is the set {a} ∪ s
containing a
and the elements of s
.
Equations
- finset.has_insert = {insert := λ (a : α) (s : finset α), {val := multiset.ndinsert a s.val, nodup := _}}
Equations
To prove a proposition about an arbitrary finset α
,
it suffices to prove it for the empty finset
,
and to show that if it holds for some finset α
,
then it holds for the finset
obtained by inserting a new element.
Inserting an element to a finite set is equivalent to the option type.
Equations
union
inter
lattice laws
Equations
- finset.lattice = {sup := has_union.union finset.has_union, le := partial_order.le finset.partial_order, lt := partial_order.lt finset.partial_order, le_refl := _, le_trans := _, lt_iff_le_not_le := _, le_antisymm := _, le_sup_left := _, le_sup_right := _, sup_le := _, inf := has_inter.inter finset.has_inter, inf_le_left := _, inf_le_right := _, le_inf := _}
Equations
- finset.semilattice_inf_bot = {bot := ∅, le := lattice.le finset.lattice, lt := lattice.lt finset.lattice, le_refl := _, le_trans := _, lt_iff_le_not_le := _, le_antisymm := _, bot_le := _, inf := lattice.inf finset.lattice, inf_le_left := _, inf_le_right := _, le_inf := _}
Equations
- finset.semilattice_sup_bot = {bot := semilattice_inf_bot.bot finset.semilattice_inf_bot, le := semilattice_inf_bot.le finset.semilattice_inf_bot, lt := semilattice_inf_bot.lt finset.semilattice_inf_bot, le_refl := _, le_trans := _, lt_iff_le_not_le := _, le_antisymm := _, bot_le := _, sup := lattice.sup finset.lattice, le_sup_left := _, le_sup_right := _, sup_le := _}
Equations
- finset.distrib_lattice = {sup := lattice.sup finset.lattice, le := lattice.le finset.lattice, lt := lattice.lt finset.lattice, le_refl := _, le_trans := _, lt_iff_le_not_le := _, le_antisymm := _, le_sup_left := _, le_sup_right := _, sup_le := _, inf := lattice.inf finset.lattice, inf_le_left := _, inf_le_right := _, le_inf := _, le_sup_inf := _}
erase
An element of s
that is not an element of erase s a
must be
a
.
sdiff
attach
piecewise
decidable equality for functions whose domain is bounded by finsets
filter
filter p s
is the set of elements of s
that satisfy p
.
Equations
- finset.filter p s = {val := multiset.filter p s.val, nodup := _}
If all elements of a finset
satisfy the predicate p
, s.filter
p
is s
.
The following instance allows us to write { x ∈ s | p x }
for finset.filter s p
.
Since the former notation requires us to define this for all propositions p
, and finset.filter
only works for decidable propositions, the notation { x ∈ s | p x }
is only compatible with
classical logic because it uses classical.prop_decidable
.
We don't want to redo all lemmas of finset.filter
for has_sep.sep
, so we make sure that simp
unfolds the notation { x ∈ s | p x }
to finset.filter s p
. If p
happens to be decidable, the
simp-lemma filter_congr_decidable
will make sure that finset.filter
uses the right instance
for decidability.
Equations
- finset.has_sep = {sep := λ (p : α → Prop) (x : finset α), finset.filter p x}
After filtering out everything that does not equal a given value, at most that value remains.
This is equivalent to filter_eq'
with the equality the other way.
After filtering out everything that does not equal a given value, at most that value remains.
This is equivalent to filter_eq
with the equality the other way.
range
range n
is the set of natural numbers less than n
.
Equations
- finset.range n = {val := multiset.range n, nodup := _}
Equivalence between the set of natural numbers which are ≥ k
and ℕ
, given by n → n - k
.
Construct an empty or singleton finset from an option
Equations
- o.to_finset = option.to_finset._match_1 o
- option.to_finset._match_1 (option.some a) = {a}
- option.to_finset._match_1 option.none = ∅
erase_dup on list and multiset
to_finset l
removes duplicates from the list l
to produce a finset.
map
When f
is an embedding of α
in β
and s
is a finset in α
, then s.map f
is the image
finset in β
. The embedding condition guarantees that there are no duplicates in the image.
Equations
- finset.map f s = {val := multiset.map ⇑f s.val, nodup := _}
Associate to an embedding f
from α
to β
the embedding that maps a finset to its image
under f
.
Equations
- finset.map_embedding f = {to_fun := finset.map f, inj' := _}
image
image f s
is the forward image of s
under f
.
Equations
- finset.image f s = (multiset.map f s.val).to_finset
Because finset.image
requires a decidable_eq
instances for the target type,
we can only construct a functor finset
when working classically.
Equations
- finset.functor = {map := λ (α β : Type u_1) (f : α → β) (s : finset α), finset.image f s, map_const := λ (α β : Type u_1), (λ (f : β → α) (s : finset β), finset.image f s) ∘ function.const β}
Equations
Given a finset s
and a predicate p
, s.subtype p
is the finset of subtype p
whose
elements belong to s
.
Equations
- finset.subtype p s = finset.map {to_fun := λ (x : {x // x ∈ finset.filter p s}), ⟨x.val, _⟩, inj' := _} (finset.filter p s).attach
s.subtype p
converts back to s.filter p
with
embedding.subtype
.
If all elements of a finset
satisfy the predicate p
,
s.subtype p
converts back to s
with embedding.subtype
.
If a finset
of a subtype is converted to the main type with
embedding.subtype
, all elements of the result have the property of
the subtype.
If a finset
of a subtype is converted to the main type with
embedding.subtype
, the result does not contain any value that does
not satisfy the property of the subtype.
If a finset
of a subtype is converted to the main type with
embedding.subtype
, the result is a subset of the set giving the
subtype.
card
Suppose that, given objects defined on all strict subsets of any finset s
, one knows how to
define an object on s
. Then one can inductively define an object on all finsets, starting from
the empty set and iterating. This can be used either to define data, or to prove properties.
Equations
- {val := s, nodup := nd}.strong_induction_on ih = s.strong_induction_on (λ (s : multiset α) (IH : Π (t : multiset α), t < s → Π (_a : t.nodup), p {val := t, nodup := _a}) (nd : s.nodup), ih {val := s, nodup := nd} (λ (_x : finset α), finset.strong_induction_on._match_1 s IH nd _x)) nd
- finset.strong_induction_on._match_1 s IH nd {val := t, nodup := nd'} = λ (ss : {val := t, nodup := nd'} ⊂ {val := s, nodup := nd}), IH t _ nd'
bind
prod
sigma
disjoint
Equations
- U.decidable_disjoint V = decidable_of_decidable_of_iff (finset.has_decidable_eq (U ⊓ V) ⊥) _
finset.fin_range k
is the finset {0, 1, ..., k-1}
, as a finset (fin k)
.
Equations
- finset.fin_range k = {val := ↑(list.fin_range k), nodup := _}
choose
Given a finset l
and a predicate p
, associate to a proof that there is a unique element of
l
satisfying p
this unique element, as an element of the corresponding subtype.
Equations
- finset.choose_x p l hp = multiset.choose_x p l.val hp
Given a finset l
and a predicate p
, associate to a proof that there is a unique element of
l
satisfying p
this unique element, as an element of the ambient type.
Equations
- finset.choose p l hp = ↑(finset.choose_x p l hp)