feat(library/data/list): define intersection for lists
This commit is contained in:
parent
d59c671054
commit
49d6d43926
2 changed files with 120 additions and 0 deletions
|
@ -637,6 +637,49 @@ assume p, by_cases
|
||||||
by rewrite [insert_eq_of_not_mem nainl₁, insert_eq_of_not_mem nainl₂]; exact (skip _ p))
|
by rewrite [insert_eq_of_not_mem nainl₁, insert_eq_of_not_mem nainl₂]; exact (skip _ p))
|
||||||
end perm_insert
|
end perm_insert
|
||||||
|
|
||||||
|
section perm_intersection
|
||||||
|
variable [H : decidable_eq A]
|
||||||
|
include H
|
||||||
|
|
||||||
|
theorem perm_intersection_left {l₁ l₂ : list A} (t₁ : list A) : l₁ ~ l₂ → (intersection l₁ t₁) ~ (intersection l₂ t₁) :=
|
||||||
|
assume p, perm.induction_on p
|
||||||
|
!refl
|
||||||
|
(λ x l₁ l₂ p₁ r₁, by_cases
|
||||||
|
(λ xint₁ : x ∈ t₁, by rewrite [*intersection_cons_of_mem _ xint₁]; exact (skip x r₁))
|
||||||
|
(λ nxint₁ : x ∉ t₁, by rewrite [*intersection_cons_of_not_mem _ nxint₁]; exact r₁))
|
||||||
|
(λ x y l, by_cases
|
||||||
|
(λ yint : y ∈ t₁, by_cases
|
||||||
|
(λ xint : x ∈ t₁,
|
||||||
|
by rewrite [*intersection_cons_of_mem _ xint, *intersection_cons_of_mem _ yint, *intersection_cons_of_mem _ xint];
|
||||||
|
exact !swap)
|
||||||
|
(λ nxint : x ∉ t₁,
|
||||||
|
by rewrite [*intersection_cons_of_mem _ yint, *intersection_cons_of_not_mem _ nxint, intersection_cons_of_mem _ yint];
|
||||||
|
exact !refl))
|
||||||
|
(λ nyint : y ∉ t₁, by_cases
|
||||||
|
(λ xint : x ∈ t₁,
|
||||||
|
by rewrite [*intersection_cons_of_mem _ xint, *intersection_cons_of_not_mem _ nyint, intersection_cons_of_mem _ xint];
|
||||||
|
exact !refl)
|
||||||
|
(λ nxint : x ∉ t₁,
|
||||||
|
by rewrite [*intersection_cons_of_not_mem _ nxint, *intersection_cons_of_not_mem _ nyint,
|
||||||
|
intersection_cons_of_not_mem _ nxint];
|
||||||
|
exact !refl)))
|
||||||
|
(λ l₁ l₂ l₃ p₁ p₂ r₁ r₂, trans r₁ r₂)
|
||||||
|
|
||||||
|
theorem perm_intersection_right (l : list A) {t₁ t₂ : list A} : t₁ ~ t₂ → (intersection l t₁) ~ (intersection l t₂) :=
|
||||||
|
list.induction_on l
|
||||||
|
(λ p, by rewrite [*intersection_nil]; exact !refl)
|
||||||
|
(λ x xs r p, by_cases
|
||||||
|
(λ xint₁ : x ∈ t₁,
|
||||||
|
assert xint₂ : x ∈ t₂, from mem_perm p xint₁,
|
||||||
|
by rewrite [intersection_cons_of_mem _ xint₁, intersection_cons_of_mem _ xint₂]; exact (skip _ (r p)))
|
||||||
|
(λ nxint₁ : x ∉ t₁,
|
||||||
|
assert nxint₂ : x ∉ t₂, from not_mem_perm p nxint₁,
|
||||||
|
by rewrite [intersection_cons_of_not_mem _ nxint₁, intersection_cons_of_not_mem _ nxint₂]; exact (r p)))
|
||||||
|
|
||||||
|
theorem perm_intersection {l₁ l₂ t₁ t₂ : list A} : l₁ ~ l₂ → t₁ ~ t₂ → (intersection l₁ t₁) ~ (intersection l₂ t₂) :=
|
||||||
|
assume p₁ p₂, trans (perm_intersection_left t₁ p₁) (perm_intersection_right l₂ p₂)
|
||||||
|
end perm_intersection
|
||||||
|
|
||||||
/- extensionality -/
|
/- extensionality -/
|
||||||
section ext
|
section ext
|
||||||
open eq.ops
|
open eq.ops
|
||||||
|
|
|
@ -543,4 +543,81 @@ assume ainl, by rewrite [insert_eq_of_mem ainl]
|
||||||
theorem length_insert_of_not_mem {a : A} {l : list A} : a ∉ l → length (insert a l) = length l + 1 :=
|
theorem length_insert_of_not_mem {a : A} {l : list A} : a ∉ l → length (insert a l) = length l + 1 :=
|
||||||
assume nainl, by rewrite [insert_eq_of_not_mem nainl]
|
assume nainl, by rewrite [insert_eq_of_not_mem nainl]
|
||||||
end insert
|
end insert
|
||||||
|
|
||||||
|
/- intersection -/
|
||||||
|
section intersection
|
||||||
|
variable {A : Type}
|
||||||
|
variable [H : decidable_eq A]
|
||||||
|
include H
|
||||||
|
|
||||||
|
definition intersection : list A → list A → list A
|
||||||
|
| [] l₂ := []
|
||||||
|
| (a::l₁) l₂ := if a ∈ l₂ then a :: intersection l₁ l₂ else intersection l₁ l₂
|
||||||
|
|
||||||
|
theorem intersection_nil (l : list A) : intersection [] l = []
|
||||||
|
|
||||||
|
theorem intersection_cons_of_mem {a : A} (l₁ : list A) {l₂} : a ∈ l₂ → intersection (a::l₁) l₂ = a :: intersection l₁ l₂ :=
|
||||||
|
assume i, if_pos i
|
||||||
|
|
||||||
|
theorem intersection_cons_of_not_mem {a : A} (l₁ : list A) {l₂} : a ∉ l₂ → intersection (a::l₁) l₂ = intersection l₁ l₂ :=
|
||||||
|
assume i, if_neg i
|
||||||
|
|
||||||
|
theorem mem_of_mem_intersection_left : ∀ {l₁ l₂} {a : A}, a ∈ intersection l₁ l₂ → a ∈ l₁
|
||||||
|
| [] l₂ a i := absurd i !not_mem_nil
|
||||||
|
| (b::l₁) l₂ a i := by_cases
|
||||||
|
(λ binl₂ : b ∈ l₂,
|
||||||
|
have aux : a ∈ b :: intersection l₁ l₂, by rewrite [intersection_cons_of_mem _ binl₂ at i]; exact i,
|
||||||
|
or.elim (eq_or_mem_of_mem_cons aux)
|
||||||
|
(λ aeqb : a = b, by rewrite [aeqb]; exact !mem_cons)
|
||||||
|
(λ aini, mem_cons_of_mem _ (mem_of_mem_intersection_left aini)))
|
||||||
|
(λ nbinl₂ : b ∉ l₂,
|
||||||
|
have ainl₁ : a ∈ l₁, by rewrite [intersection_cons_of_not_mem _ nbinl₂ at i]; exact (mem_of_mem_intersection_left i),
|
||||||
|
mem_cons_of_mem _ ainl₁)
|
||||||
|
|
||||||
|
theorem mem_of_mem_intersection_right : ∀ {l₁ l₂} {a : A}, a ∈ intersection l₁ l₂ → a ∈ l₂
|
||||||
|
| [] l₂ a i := absurd i !not_mem_nil
|
||||||
|
| (b::l₁) l₂ a i := by_cases
|
||||||
|
(λ binl₂ : b ∈ l₂,
|
||||||
|
have aux : a ∈ b :: intersection l₁ l₂, by rewrite [intersection_cons_of_mem _ binl₂ at i]; exact i,
|
||||||
|
or.elim (eq_or_mem_of_mem_cons aux)
|
||||||
|
(λ aeqb : a = b, by rewrite [aeqb]; exact binl₂)
|
||||||
|
(λ aini : a ∈ intersection l₁ l₂, mem_of_mem_intersection_right aini))
|
||||||
|
(λ nbinl₂ : b ∉ l₂,
|
||||||
|
by rewrite [intersection_cons_of_not_mem _ nbinl₂ at i]; exact (mem_of_mem_intersection_right i))
|
||||||
|
|
||||||
|
theorem mem_intersection_of_mem_of_men : ∀ {l₁ l₂} {a : A}, a ∈ l₁ → a ∈ l₂ → a ∈ intersection l₁ l₂
|
||||||
|
| [] l₂ a i₁ i₂ := absurd i₁ !not_mem_nil
|
||||||
|
| (b::l₁) l₂ a i₁ i₂ := by_cases
|
||||||
|
(λ binl₂ : b ∈ l₂,
|
||||||
|
or.elim (eq_or_mem_of_mem_cons i₁)
|
||||||
|
(λ aeqb : a = b,
|
||||||
|
by rewrite [intersection_cons_of_mem _ binl₂, aeqb]; exact !mem_cons)
|
||||||
|
(λ ainl₁ : a ∈ l₁,
|
||||||
|
by rewrite [intersection_cons_of_mem _ binl₂];
|
||||||
|
apply mem_cons_of_mem;
|
||||||
|
exact (mem_intersection_of_mem_of_men ainl₁ i₂)))
|
||||||
|
(λ nbinl₂ : b ∉ l₂,
|
||||||
|
or.elim (eq_or_mem_of_mem_cons i₁)
|
||||||
|
(λ aeqb : a = b, absurd (aeqb ▸ i₂) nbinl₂)
|
||||||
|
(λ ainl₁ : a ∈ l₁,
|
||||||
|
by rewrite [intersection_cons_of_not_mem _ nbinl₂]; exact (mem_intersection_of_mem_of_men ainl₁ i₂)))
|
||||||
|
|
||||||
|
theorem nodup_intersection_of_nodup : ∀ {l₁ : list A} (l₂), nodup l₁ → nodup (intersection l₁ l₂)
|
||||||
|
| [] l₂ d := nodup_nil
|
||||||
|
| (a::l₁) l₂ d :=
|
||||||
|
have d₁ : nodup l₁, from nodup_of_nodup_cons d,
|
||||||
|
assert d₂ : nodup (intersection l₁ l₂), from nodup_intersection_of_nodup _ d₁,
|
||||||
|
have nainl₁ : a ∉ l₁, from not_mem_of_nodup_cons d,
|
||||||
|
assert naini : a ∉ intersection l₁ l₂, from λ i, absurd (mem_of_mem_intersection_left i) nainl₁,
|
||||||
|
by_cases
|
||||||
|
(λ ainl₂ : a ∈ l₂, by rewrite [intersection_cons_of_mem _ ainl₂]; exact (nodup_cons naini d₂))
|
||||||
|
(λ nainl₂ : a ∉ l₂, by rewrite [intersection_cons_of_not_mem _ nainl₂]; exact d₂)
|
||||||
|
|
||||||
|
theorem intersection_eq_nil_of_disjoint : ∀ {l₁ l₂ : list A}, disjoint l₁ l₂ → intersection l₁ l₂ = []
|
||||||
|
| [] l₂ d := rfl
|
||||||
|
| (a::l₁) l₂ d :=
|
||||||
|
assert aux_eq : intersection l₁ l₂ = [], from intersection_eq_nil_of_disjoint (disjoint_of_disjoint_cons_left d),
|
||||||
|
assert nainl₂ : a ∉ l₂, from disjoint_left d !mem_cons,
|
||||||
|
by rewrite [intersection_cons_of_not_mem _ nainl₂, aux_eq]
|
||||||
|
end intersection
|
||||||
end list
|
end list
|
||||||
|
|
Loading…
Reference in a new issue