2015-04-11 00:14:10 +00:00
|
|
|
|
/-
|
|
|
|
|
Copyright (c) 2015 Microsoft Corporation. All rights reserved.
|
|
|
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
2015-05-08 03:36:03 +00:00
|
|
|
|
Author: Leonardo de Moura, Jeremy Avigad
|
2015-04-11 00:14:10 +00:00
|
|
|
|
|
2015-05-08 03:36:03 +00:00
|
|
|
|
Combinators for finite sets.
|
2015-04-11 00:14:10 +00:00
|
|
|
|
-/
|
2015-04-11 16:28:27 +00:00
|
|
|
|
import data.finset.basic logic.identities
|
2015-04-11 00:14:10 +00:00
|
|
|
|
open list quot subtype decidable perm function
|
|
|
|
|
|
|
|
|
|
namespace finset
|
2015-05-08 03:36:03 +00:00
|
|
|
|
|
2015-05-10 07:44:08 +00:00
|
|
|
|
/- image (corresponds to map on list) -/
|
|
|
|
|
section image
|
2015-04-11 00:14:10 +00:00
|
|
|
|
variables {A B : Type}
|
|
|
|
|
variable [h : decidable_eq B]
|
|
|
|
|
include h
|
|
|
|
|
|
2015-05-10 07:44:08 +00:00
|
|
|
|
definition image (f : A → B) (s : finset A) : finset B :=
|
2015-04-11 00:14:10 +00:00
|
|
|
|
quot.lift_on s
|
|
|
|
|
(λ l, to_finset (list.map f (elt_of l)))
|
|
|
|
|
(λ l₁ l₂ p, quot.sound (perm_erase_dup_of_perm (perm_map _ p)))
|
|
|
|
|
|
2015-05-10 07:44:08 +00:00
|
|
|
|
theorem image_empty (f : A → B) : image f ∅ = ∅ :=
|
2015-04-11 00:14:10 +00:00
|
|
|
|
rfl
|
2015-05-10 07:44:08 +00:00
|
|
|
|
|
|
|
|
|
theorem mem_image_of_mem (f : A → B) {s : finset A} {a : A} : a ∈ s → f a ∈ image f s :=
|
|
|
|
|
quot.induction_on s (take l, assume H : a ∈ elt_of l, mem_to_finset (mem_map f H))
|
|
|
|
|
|
2015-05-10 10:07:03 +00:00
|
|
|
|
theorem mem_image_of_mem_of_eq {f : A → B} {s : finset A} {a : A} {b : B}
|
|
|
|
|
(H1 : a ∈ s) (H2 : f a = b) :
|
|
|
|
|
b ∈ image f s :=
|
|
|
|
|
eq.subst H2 (mem_image_of_mem f H1)
|
|
|
|
|
|
2015-05-10 07:44:08 +00:00
|
|
|
|
theorem exists_of_mem_image {f : A → B} {s : finset A} {b : B} :
|
|
|
|
|
b ∈ image f s → ∃a, a ∈ s ∧ f a = b :=
|
|
|
|
|
quot.induction_on s
|
|
|
|
|
(take l, assume H : b ∈ erase_dup (list.map f (elt_of l)),
|
|
|
|
|
exists_of_mem_map (mem_of_mem_erase_dup H))
|
|
|
|
|
|
|
|
|
|
theorem mem_image_iff (f : A → B) {s : finset A} {y : B} : y ∈ image f s ↔ ∃x, x ∈ s ∧ f x = y :=
|
|
|
|
|
iff.intro exists_of_mem_image
|
|
|
|
|
(assume H,
|
2015-05-11 16:14:48 +00:00
|
|
|
|
obtain x (H₁ : x ∈ s) (H₂ : f x = y), from H,
|
|
|
|
|
mem_image_of_mem_of_eq H₁ H₂)
|
2015-05-10 07:44:08 +00:00
|
|
|
|
|
|
|
|
|
theorem mem_image_eq (f : A → B) {s : finset A} {y : B} : y ∈ image f s = ∃x, x ∈ s ∧ f x = y :=
|
|
|
|
|
propext (mem_image_iff f)
|
2015-05-10 10:07:03 +00:00
|
|
|
|
|
|
|
|
|
theorem mem_image_of_mem_image_of_subset {f : A → B} {s t : finset A} {y : B}
|
|
|
|
|
(H1 : y ∈ image f s) (H2 : s ⊆ t) : y ∈ image f t :=
|
2015-05-11 16:14:48 +00:00
|
|
|
|
obtain x (H3: x ∈ s) (H4 : f x = y), from exists_of_mem_image H1,
|
|
|
|
|
have H5 : x ∈ t, from mem_of_subset_of_mem H2 H3,
|
|
|
|
|
show y ∈ image f t, from mem_image_of_mem_of_eq H5 H4
|
2015-05-10 10:07:03 +00:00
|
|
|
|
|
|
|
|
|
theorem image_insert [h' : decidable_eq A] (f : A → B) (s : finset A) (a : A) :
|
|
|
|
|
image f (insert a s) = insert (f a) (image f s) :=
|
|
|
|
|
ext (take y, iff.intro
|
|
|
|
|
(assume H : y ∈ image f (insert a s),
|
2015-05-11 16:14:48 +00:00
|
|
|
|
obtain x (H1l : x ∈ insert a s) (H1r :f x = y), from exists_of_mem_image H,
|
|
|
|
|
have H2 : x = a ∨ x ∈ s, from eq_or_mem_of_mem_insert H1l,
|
2015-05-10 10:07:03 +00:00
|
|
|
|
or.elim H2
|
|
|
|
|
(assume H3 : x = a,
|
2015-05-11 16:14:48 +00:00
|
|
|
|
have H4 : f a = y, from eq.subst H3 H1r,
|
2015-05-10 10:07:03 +00:00
|
|
|
|
show y ∈ insert (f a) (image f s), from eq.subst H4 !mem_insert)
|
|
|
|
|
(assume H3 : x ∈ s,
|
|
|
|
|
have H5 : f x ∈ image f s, from mem_image_of_mem f H3,
|
2015-05-11 16:14:48 +00:00
|
|
|
|
show y ∈ insert (f a) (image f s), from eq.subst H1r (mem_insert_of_mem _ H5)))
|
2015-05-10 10:07:03 +00:00
|
|
|
|
(assume H : y ∈ insert (f a) (image f s),
|
|
|
|
|
have H1 : y = f a ∨ y ∈ image f s, from eq_or_mem_of_mem_insert H,
|
|
|
|
|
or.elim H1
|
|
|
|
|
(assume H2 : y = f a,
|
|
|
|
|
have H3 : f a ∈ image f (insert a s), from mem_image_of_mem f !mem_insert,
|
|
|
|
|
show y ∈ image f (insert a s), from eq.subst (eq.symm H2) H3)
|
|
|
|
|
(assume H2 : y ∈ image f s,
|
|
|
|
|
show y ∈ image f (insert a s), from mem_image_of_mem_image_of_subset H2 !subset_insert)))
|
2015-07-11 01:58:20 +00:00
|
|
|
|
|
|
|
|
|
lemma image_compose {C : Type} [deceqC : decidable_eq C] {f : B → C} {g : A → B} {s : finset A} :
|
|
|
|
|
image (f∘g) s = image f (image g s) :=
|
|
|
|
|
ext (take z, iff.intro
|
|
|
|
|
(assume Hz : z ∈ image (f∘g) s,
|
|
|
|
|
obtain x (Hx : x ∈ s) (Hgfx : f (g x) = z), from exists_of_mem_image Hz,
|
|
|
|
|
by rewrite -Hgfx; apply mem_image_of_mem _ (mem_image_of_mem _ Hx))
|
|
|
|
|
(assume Hz : z ∈ image f (image g s),
|
|
|
|
|
obtain y (Hy : y ∈ image g s) (Hfy : f y = z), from exists_of_mem_image Hz,
|
|
|
|
|
obtain x (Hx : x ∈ s) (Hgx : g x = y), from exists_of_mem_image Hy,
|
|
|
|
|
mem_image_of_mem_of_eq Hx (by esimp; rewrite [Hgx, Hfy])))
|
|
|
|
|
|
2015-05-10 07:44:08 +00:00
|
|
|
|
end image
|
2015-04-11 16:28:27 +00:00
|
|
|
|
|
2015-05-08 03:36:03 +00:00
|
|
|
|
/- filter and set-builder notation -/
|
|
|
|
|
section filter
|
2015-05-10 07:44:08 +00:00
|
|
|
|
variables {A : Type} [deceq : decidable_eq A]
|
|
|
|
|
include deceq
|
|
|
|
|
variables (p : A → Prop) [decp : decidable_pred p] (s : finset A) {x : A}
|
|
|
|
|
include decp
|
|
|
|
|
|
|
|
|
|
definition filter : finset A :=
|
|
|
|
|
quot.lift_on s
|
|
|
|
|
(λl, to_finset_of_nodup
|
|
|
|
|
(list.filter p (subtype.elt_of l))
|
|
|
|
|
(list.nodup_filter p (subtype.has_property l)))
|
|
|
|
|
(λ l₁ l₂ u, quot.sound (perm.perm_filter u))
|
2015-05-08 03:36:03 +00:00
|
|
|
|
|
2015-05-10 07:44:08 +00:00
|
|
|
|
notation `{` binders ∈ s `|` r:(scoped:1 p, filter p s) `}` := r
|
2015-05-08 03:36:03 +00:00
|
|
|
|
|
2015-05-10 07:44:08 +00:00
|
|
|
|
theorem filter_empty : filter p ∅ = ∅ := rfl
|
2015-05-08 03:36:03 +00:00
|
|
|
|
|
2015-05-10 07:44:08 +00:00
|
|
|
|
variables {p s}
|
2015-05-08 03:36:03 +00:00
|
|
|
|
|
2015-05-10 07:44:08 +00:00
|
|
|
|
theorem of_mem_filter : x ∈ filter p s → p x :=
|
|
|
|
|
quot.induction_on s (take l, list.of_mem_filter)
|
2015-05-08 03:36:03 +00:00
|
|
|
|
|
2015-05-10 07:44:08 +00:00
|
|
|
|
theorem mem_of_mem_filter : x ∈ filter p s → x ∈ s :=
|
|
|
|
|
quot.induction_on s (take l, list.mem_of_mem_filter)
|
2015-05-08 03:36:03 +00:00
|
|
|
|
|
2015-05-10 07:44:08 +00:00
|
|
|
|
theorem mem_filter_of_mem {x : A} : x ∈ s → p x → x ∈ filter p s :=
|
|
|
|
|
quot.induction_on s (take l, list.mem_filter_of_mem)
|
2015-05-08 03:36:03 +00:00
|
|
|
|
|
2015-05-10 07:44:08 +00:00
|
|
|
|
variables (p s)
|
2015-05-08 03:36:03 +00:00
|
|
|
|
|
2015-05-10 07:44:08 +00:00
|
|
|
|
theorem mem_filter_iff : x ∈ filter p s ↔ x ∈ s ∧ p x :=
|
|
|
|
|
iff.intro
|
|
|
|
|
(assume H, and.intro (mem_of_mem_filter H) (of_mem_filter H))
|
|
|
|
|
(assume H, mem_filter_of_mem (and.left H) (and.right H))
|
2015-05-08 03:36:03 +00:00
|
|
|
|
|
2015-05-10 07:44:08 +00:00
|
|
|
|
theorem mem_filter_eq : x ∈ filter p s = (x ∈ s ∧ p x) :=
|
|
|
|
|
propext !mem_filter_iff
|
2015-05-08 03:36:03 +00:00
|
|
|
|
end filter
|
|
|
|
|
|
|
|
|
|
/- set difference -/
|
|
|
|
|
section diff
|
2015-05-10 07:44:08 +00:00
|
|
|
|
variables {A : Type} [deceq : decidable_eq A]
|
|
|
|
|
include deceq
|
|
|
|
|
|
|
|
|
|
definition diff (s t : finset A) : finset A := {x ∈ s | x ∉ t}
|
|
|
|
|
infix `\`:70 := diff
|
|
|
|
|
|
|
|
|
|
theorem mem_of_mem_diff {s t : finset A} {x : A} (H : x ∈ s \ t) : x ∈ s :=
|
|
|
|
|
mem_of_mem_filter H
|
|
|
|
|
|
|
|
|
|
theorem not_mem_of_mem_diff {s t : finset A} {x : A} (H : x ∈ s \ t) : x ∉ t :=
|
|
|
|
|
of_mem_filter H
|
|
|
|
|
|
|
|
|
|
theorem mem_diff {s t : finset A} {x : A} (H1 : x ∈ s) (H2 : x ∉ t) : x ∈ s \ t :=
|
|
|
|
|
mem_filter_of_mem H1 H2
|
|
|
|
|
|
|
|
|
|
theorem mem_diff_iff (s t : finset A) (x : A) : x ∈ s \ t ↔ x ∈ s ∧ x ∉ t :=
|
|
|
|
|
iff.intro
|
|
|
|
|
(assume H, and.intro (mem_of_mem_diff H) (not_mem_of_mem_diff H))
|
|
|
|
|
(assume H, mem_diff (and.left H) (and.right H))
|
|
|
|
|
|
|
|
|
|
theorem mem_diff_eq (s t : finset A) (x : A) : x ∈ s \ t = (x ∈ s ∧ x ∉ t) :=
|
|
|
|
|
propext !mem_diff_iff
|
|
|
|
|
|
|
|
|
|
theorem union_diff_cancel {s t : finset A} (H : s ⊆ t) : s ∪ (t \ s) = t :=
|
|
|
|
|
ext (take x, iff.intro
|
|
|
|
|
(assume H1 : x ∈ s ∪ (t \ s),
|
|
|
|
|
or.elim (mem_or_mem_of_mem_union H1)
|
|
|
|
|
(assume H2 : x ∈ s, mem_of_subset_of_mem H H2)
|
|
|
|
|
(assume H2 : x ∈ t \ s, mem_of_mem_diff H2))
|
|
|
|
|
(assume H1 : x ∈ t,
|
|
|
|
|
decidable.by_cases
|
|
|
|
|
(assume H2 : x ∈ s, mem_union_left _ H2)
|
|
|
|
|
(assume H2 : x ∉ s, mem_union_right _ (mem_diff H1 H2))))
|
|
|
|
|
|
|
|
|
|
theorem diff_union_cancel {s t : finset A} (H : s ⊆ t) : (t \ s) ∪ s = t :=
|
|
|
|
|
eq.subst !union.comm (!union_diff_cancel H)
|
2015-05-08 03:36:03 +00:00
|
|
|
|
end diff
|
|
|
|
|
|
|
|
|
|
/- all -/
|
2015-04-11 16:28:27 +00:00
|
|
|
|
section all
|
|
|
|
|
variables {A : Type}
|
|
|
|
|
definition all (s : finset A) (p : A → Prop) : Prop :=
|
|
|
|
|
quot.lift_on s
|
|
|
|
|
(λ l, all (elt_of l) p)
|
|
|
|
|
(λ l₁ l₂ p, foldr_eq_of_perm (λ a₁ a₂ q, propext !and.left_comm) p true)
|
|
|
|
|
|
|
|
|
|
theorem all_empty (p : A → Prop) : all ∅ p = true :=
|
|
|
|
|
rfl
|
|
|
|
|
|
|
|
|
|
theorem of_mem_of_all {p : A → Prop} {a : A} {s : finset A} : a ∈ s → all s p → p a :=
|
|
|
|
|
quot.induction_on s (λ l i h, list.of_mem_of_all i h)
|
|
|
|
|
|
2015-05-09 21:33:56 +00:00
|
|
|
|
theorem forall_of_all {p : A → Prop} {s : finset A} (H : all s p) : ∀{a}, a ∈ s → p a :=
|
|
|
|
|
λ a H', of_mem_of_all H' H
|
|
|
|
|
|
2015-05-10 07:44:08 +00:00
|
|
|
|
theorem all_of_forall {p : A → Prop} {s : finset A} : (∀a, a ∈ s → p a) → all s p :=
|
|
|
|
|
quot.induction_on s (λ l H, list.all_of_forall H)
|
|
|
|
|
|
|
|
|
|
theorem all_iff_forall (p : A → Prop) (s : finset A) : all s p ↔ (∀a, a ∈ s → p a) :=
|
|
|
|
|
iff.intro forall_of_all all_of_forall
|
|
|
|
|
|
|
|
|
|
definition decidable_all [instance] (p : A → Prop) [h : decidable_pred p] (s : finset A) :
|
|
|
|
|
decidable (all s p) :=
|
2015-05-09 21:33:56 +00:00
|
|
|
|
quot.rec_on_subsingleton s (λ l, list.decidable_all p (elt_of l))
|
|
|
|
|
|
2015-04-11 16:28:27 +00:00
|
|
|
|
theorem all_implies {p q : A → Prop} {s : finset A} : all s p → (∀ x, p x → q x) → all s q :=
|
|
|
|
|
quot.induction_on s (λ l h₁ h₂, list.all_implies h₁ h₂)
|
|
|
|
|
|
|
|
|
|
variable [h : decidable_eq A]
|
|
|
|
|
include h
|
|
|
|
|
|
|
|
|
|
theorem all_union {p : A → Prop} {s₁ s₂ : finset A} : all s₁ p → all s₂ p → all (s₁ ∪ s₂) p :=
|
|
|
|
|
quot.induction_on₂ s₁ s₂ (λ l₁ l₂ a₁ a₂, all_union a₁ a₂)
|
|
|
|
|
|
|
|
|
|
theorem all_of_all_union_left {p : A → Prop} {s₁ s₂ : finset A} : all (s₁ ∪ s₂) p → all s₁ p :=
|
|
|
|
|
quot.induction_on₂ s₁ s₂ (λ l₁ l₂ a, list.all_of_all_union_left a)
|
|
|
|
|
|
|
|
|
|
theorem all_of_all_union_right {p : A → Prop} {s₁ s₂ : finset A} : all (s₁ ∪ s₂) p → all s₂ p :=
|
|
|
|
|
quot.induction_on₂ s₁ s₂ (λ l₁ l₂ a, list.all_of_all_union_right a)
|
|
|
|
|
|
|
|
|
|
theorem all_insert_of_all {p : A → Prop} {a : A} {s : finset A} : p a → all s p → all (insert a s) p :=
|
|
|
|
|
quot.induction_on s (λ l h₁ h₂, list.all_insert_of_all h₁ h₂)
|
|
|
|
|
|
|
|
|
|
theorem all_erase_of_all {p : A → Prop} (a : A) {s : finset A}: all s p → all (erase a s) p :=
|
|
|
|
|
quot.induction_on s (λ l h, list.all_erase_of_all a h)
|
|
|
|
|
|
2015-05-05 15:53:31 +00:00
|
|
|
|
theorem all_inter_of_all_left {p : A → Prop} {s₁ : finset A} (s₂ : finset A) : all s₁ p → all (s₁ ∩ s₂) p :=
|
|
|
|
|
quot.induction_on₂ s₁ s₂ (λ l₁ l₂ h, list.all_inter_of_all_left _ h)
|
2015-04-11 16:28:27 +00:00
|
|
|
|
|
2015-05-05 15:53:31 +00:00
|
|
|
|
theorem all_inter_of_all_right {p : A → Prop} {s₁ : finset A} (s₂ : finset A) : all s₂ p → all (s₁ ∩ s₂) p :=
|
|
|
|
|
quot.induction_on₂ s₁ s₂ (λ l₁ l₂ h, list.all_inter_of_all_right _ h)
|
2015-05-10 07:44:08 +00:00
|
|
|
|
|
|
|
|
|
theorem subset_iff_all (s t : finset A) : s ⊆ t ↔ all s (λ x, x ∈ t) :=
|
|
|
|
|
iff.intro
|
|
|
|
|
(assume H : s ⊆ t, all_of_forall (take x, assume H1, mem_of_subset_of_mem H H1))
|
|
|
|
|
(assume H : all s (λ x, x ∈ t), subset_of_forall (take x, assume H1 : x ∈ s, of_mem_of_all H1 H))
|
|
|
|
|
|
|
|
|
|
definition decidable_subset [instance] (s t : finset A) : decidable (s ⊆ t) :=
|
|
|
|
|
decidable_of_decidable_of_iff _ (iff.symm !subset_iff_all)
|
2015-04-11 16:28:27 +00:00
|
|
|
|
end all
|
2015-04-12 02:46:04 +00:00
|
|
|
|
|
2015-05-09 21:33:56 +00:00
|
|
|
|
/- any -/
|
|
|
|
|
section any
|
|
|
|
|
variables {A : Type}
|
|
|
|
|
definition any (s : finset A) (p : A → Prop) : Prop :=
|
|
|
|
|
quot.lift_on s
|
|
|
|
|
(λ l, any (elt_of l) p)
|
|
|
|
|
(λ l₁ l₂ p, foldr_eq_of_perm (λ a₁ a₂ q, propext !or.left_comm) p false)
|
|
|
|
|
|
|
|
|
|
theorem any_empty (p : A → Prop) : any ∅ p = false := rfl
|
|
|
|
|
|
|
|
|
|
theorem exists_of_any {p : A → Prop} {s : finset A} : any s p → ∃a, a ∈ s ∧ p a :=
|
|
|
|
|
quot.induction_on s (λ l H, list.exists_of_any H)
|
|
|
|
|
|
|
|
|
|
theorem any_of_mem {p : A → Prop} {s : finset A} {a : A} : a ∈ s → p a → any s p :=
|
|
|
|
|
quot.induction_on s (λ l H1 H2, list.any_of_mem H1 H2)
|
|
|
|
|
|
2015-05-10 07:44:08 +00:00
|
|
|
|
theorem any_of_exists {p : A → Prop} {s : finset A} (H : ∃a, a ∈ s ∧ p a) : any s p :=
|
2015-05-11 16:14:48 +00:00
|
|
|
|
obtain a H₁ H₂, from H,
|
|
|
|
|
any_of_mem H₁ H₂
|
2015-05-10 07:44:08 +00:00
|
|
|
|
|
|
|
|
|
theorem any_iff_exists (p : A → Prop) (s : finset A) : any s p ↔ (∃a, a ∈ s ∧ p a) :=
|
|
|
|
|
iff.intro exists_of_any any_of_exists
|
|
|
|
|
|
2015-05-09 21:33:56 +00:00
|
|
|
|
theorem any_of_insert [h : decidable_eq A] {p : A → Prop} (s : finset A) {a : A} (H : p a) :
|
|
|
|
|
any (insert a s) p :=
|
|
|
|
|
any_of_mem (mem_insert a s) H
|
|
|
|
|
|
|
|
|
|
theorem any_of_insert_right [h : decidable_eq A] {p : A → Prop} {s : finset A} (a : A) (H : any s p) :
|
|
|
|
|
any (insert a s) p :=
|
2015-05-11 16:14:48 +00:00
|
|
|
|
obtain b (H₁ : b ∈ s) (H₂ : p b), from exists_of_any H,
|
|
|
|
|
any_of_mem (mem_insert_of_mem a H₁) H₂
|
2015-05-09 21:33:56 +00:00
|
|
|
|
|
2015-05-10 07:44:08 +00:00
|
|
|
|
definition decidable_any [instance] (p : A → Prop) [h : decidable_pred p] (s : finset A) :
|
|
|
|
|
decidable (any s p) :=
|
2015-05-09 21:33:56 +00:00
|
|
|
|
quot.rec_on_subsingleton s (λ l, list.decidable_any p (elt_of l))
|
|
|
|
|
end any
|
|
|
|
|
|
2015-05-08 03:46:14 +00:00
|
|
|
|
section product
|
2015-04-12 02:46:04 +00:00
|
|
|
|
variables {A B : Type}
|
2015-05-08 03:46:14 +00:00
|
|
|
|
definition product (s₁ : finset A) (s₂ : finset B) : finset (A × B) :=
|
2015-04-12 02:46:04 +00:00
|
|
|
|
quot.lift_on₂ s₁ s₂
|
|
|
|
|
(λ l₁ l₂,
|
2015-05-08 04:00:55 +00:00
|
|
|
|
to_finset_of_nodup (product (elt_of l₁) (elt_of l₂))
|
2015-05-08 03:46:14 +00:00
|
|
|
|
(nodup_product (has_property l₁) (has_property l₂)))
|
|
|
|
|
(λ v₁ v₂ w₁ w₂ p₁ p₂, quot.sound (perm_product p₁ p₂))
|
2015-04-12 02:46:04 +00:00
|
|
|
|
|
2015-05-08 03:46:14 +00:00
|
|
|
|
infix * := product
|
2015-04-12 02:46:04 +00:00
|
|
|
|
|
2015-05-08 03:46:14 +00:00
|
|
|
|
theorem empty_product (s : finset B) : @empty A * s = ∅ :=
|
2015-04-12 02:46:04 +00:00
|
|
|
|
quot.induction_on s (λ l, rfl)
|
|
|
|
|
|
2015-05-08 03:46:14 +00:00
|
|
|
|
theorem mem_product {a : A} {b : B} {s₁ : finset A} {s₂ : finset B}
|
2015-04-12 02:46:04 +00:00
|
|
|
|
: a ∈ s₁ → b ∈ s₂ → (a, b) ∈ s₁ * s₂ :=
|
2015-05-08 03:46:14 +00:00
|
|
|
|
quot.induction_on₂ s₁ s₂ (λ l₁ l₂ i₁ i₂, list.mem_product i₁ i₂)
|
2015-04-12 02:46:04 +00:00
|
|
|
|
|
2015-05-08 03:46:14 +00:00
|
|
|
|
theorem mem_of_mem_product_left {a : A} {b : B} {s₁ : finset A} {s₂ : finset B}
|
2015-04-12 02:46:04 +00:00
|
|
|
|
: (a, b) ∈ s₁ * s₂ → a ∈ s₁ :=
|
2015-05-08 03:46:14 +00:00
|
|
|
|
quot.induction_on₂ s₁ s₂ (λ l₁ l₂ i, list.mem_of_mem_product_left i)
|
2015-04-12 02:46:04 +00:00
|
|
|
|
|
2015-05-08 03:46:14 +00:00
|
|
|
|
theorem mem_of_mem_product_right {a : A} {b : B} {s₁ : finset A} {s₂ : finset B}
|
2015-04-12 02:46:04 +00:00
|
|
|
|
: (a, b) ∈ s₁ * s₂ → b ∈ s₂ :=
|
2015-05-08 03:46:14 +00:00
|
|
|
|
quot.induction_on₂ s₁ s₂ (λ l₁ l₂ i, list.mem_of_mem_product_right i)
|
2015-04-12 02:46:04 +00:00
|
|
|
|
|
2015-05-08 03:46:14 +00:00
|
|
|
|
theorem product_empty (s : finset A) : s * @empty B = ∅ :=
|
2015-04-12 02:46:04 +00:00
|
|
|
|
ext (λ p,
|
|
|
|
|
match p with
|
|
|
|
|
| (a, b) := iff.intro
|
2015-05-08 03:46:14 +00:00
|
|
|
|
(λ i, absurd (mem_of_mem_product_right i) !not_mem_empty)
|
2015-04-12 02:46:04 +00:00
|
|
|
|
(λ i, absurd i !not_mem_empty)
|
|
|
|
|
end)
|
2015-05-08 03:46:14 +00:00
|
|
|
|
end product
|
2015-04-11 00:14:10 +00:00
|
|
|
|
end finset
|