Forked from
Iris / stdpp
2662 commits behind the upstream repository.
-
Robbert Krebbers authored
The port makes the following notable changes: * The carrier types of separation algebras and integer environments are no longer in Set. Now they have a type at a fixed type level above Set. This both works better in 8.5 and makes the formalization more general. I have tried putting them at polymorphic type levels, but that increased the compilation time by an order of magnitude. * I am using a custom f_equal tactic written in Ltac to circumvent bug #4069. That bug has been fixed, so this custom tactic can be removed when the next beta of 8.5 is out.
Robbert Krebbers authoredThe port makes the following notable changes: * The carrier types of separation algebras and integer environments are no longer in Set. Now they have a type at a fixed type level above Set. This both works better in 8.5 and makes the formalization more general. I have tried putting them at polymorphic type levels, but that increased the compilation time by an order of magnitude. * I am using a custom f_equal tactic written in Ltac to circumvent bug #4069. That bug has been fixed, so this custom tactic can be removed when the next beta of 8.5 is out.
orders.v 24.27 KiB
(* Copyright (c) 2012-2015, Robbert Krebbers. *)
(* This file is distributed under the terms of the BSD license. *)
(** This file collects common properties of pre-orders and semi lattices. This
theory will mainly be used for the theory on collections and finite maps. *)
Require Export Sorted.
Require Export base decidable tactics list.
(** * Arbitrary pre-, parial and total orders *)
(** Properties about arbitrary pre-, partial, and total orders. We do not use
the relation [⊆] because we often have multiple orders on the same structure *)
Section orders.
Context {A} {R : relation A}.
Implicit Types X Y : A.
Infix "⊆" := R.
Notation "X ⊈ Y" := (¬X ⊆ Y).
Infix "⊂" := (strict R).
Lemma reflexive_eq `{!Reflexive R} X Y : X = Y → X ⊆ Y.
Proof. by intros <-. Qed.
Lemma anti_symmetric_iff `{!PartialOrder R} X Y : X = Y ↔ R X Y ∧ R Y X.
Proof. split. by intros ->. by intros [??]; apply (anti_symmetric _). Qed.
Lemma strict_spec X Y : X ⊂ Y ↔ X ⊆ Y ∧ Y ⊈ X.
Proof. done. Qed.
Lemma strict_include X Y : X ⊂ Y → X ⊆ Y.
Proof. by intros [? _]. Qed.
Lemma strict_ne X Y : X ⊂ Y → X ≠ Y.
Proof. by intros [??] <-. Qed.
Lemma strict_ne_sym X Y : X ⊂ Y → Y ≠ X.
Proof. by intros [??] <-. Qed.
Lemma strict_transitive_l `{!Transitive R} X Y Z : X ⊂ Y → Y ⊆ Z → X ⊂ Z.
Proof.
intros [? HXY] ?. split; [by transitivity Y|].
contradict HXY. by transitivity Z.
Qed.
Lemma strict_transitive_r `{!Transitive R} X Y Z : X ⊆ Y → Y ⊂ Z → X ⊂ Z.
Proof.
intros ? [? HYZ]. split; [by transitivity Y|].
contradict HYZ. by transitivity X.
Qed.
Global Instance: Irreflexive (strict R).
Proof. firstorder. Qed.
Global Instance: Transitive R → StrictOrder (strict R).
Proof.
split; try apply _.
eauto using strict_transitive_r, strict_include.
Qed.
Global Instance preorder_subset_dec_slow `{∀ X Y, Decision (X ⊆ Y)}
(X Y : A) : Decision (X ⊂ Y) | 100 := _.
Lemma strict_spec_alt `{!AntiSymmetric (=) R} X Y : X ⊂ Y ↔ X ⊆ Y ∧ X ≠ Y.
Proof.
split.
* intros [? HYX]. split. done. by intros <-.
* intros [? HXY]. split. done. by contradict HXY; apply (anti_symmetric R).
Qed.
Lemma po_eq_dec `{!PartialOrder R, ∀ X Y, Decision (X ⊆ Y)} (X Y : A) :
Decision (X = Y).
Proof.
refine (cast_if_and (decide (X ⊆ Y)) (decide (Y ⊆ X)));
abstract (rewrite anti_symmetric_iff; tauto).
Defined.
Lemma total_not `{!Total R} X Y : X ⊈ Y → Y ⊆ X.
Proof. intros. destruct (total R X Y); tauto. Qed.
Lemma total_not_strict `{!Total R} X Y : X ⊈ Y → Y ⊂ X.
Proof. red; auto using total_not. Qed.
Global Instance trichotomy_total
`{!Trichotomy (strict R), !Reflexive R} : Total R.
Proof.
intros X Y.
destruct (trichotomy (strict R) X Y) as [[??]|[<-|[??]]]; intuition.
Qed.
End orders.
Section strict_orders.
Context {A} {R : relation A}.
Implicit Types X Y : A.
Infix "⊂" := R.
Lemma irreflexive_eq `{!Irreflexive R} X Y : X = Y → ¬X ⊂ Y.
Proof. intros ->. apply (irreflexivity R). Qed.
Lemma strict_anti_symmetric `{!StrictOrder R} X Y :
X ⊂ Y → Y ⊂ X → False.
Proof. intros. apply (irreflexivity R X). by transitivity Y. Qed.
Global Instance trichotomyT_dec `{!TrichotomyT R, !StrictOrder R} X Y :
Decision (X ⊂ Y) :=
match trichotomyT R X Y with
| inleft (left H) => left H
| inleft (right H) => right (irreflexive_eq _ _ H)
| inright H => right (strict_anti_symmetric _ _ H)
end.
Global Instance trichotomyT_trichotomy `{!TrichotomyT R} : Trichotomy R.
Proof. intros X Y. destruct (trichotomyT R X Y) as [[|]|]; tauto. Qed.
End strict_orders.
Ltac simplify_order := repeat
match goal with
| _ => progress simplify_equality
| H : ?R ?x ?x |- _ => by destruct (irreflexivity _ _ H)
| H1 : ?R ?x ?y |- _ =>
match goal with
| H2 : R y x |- _ =>
assert (x = y) by (by apply (anti_symmetric R)); clear H1 H2
| H2 : R y ?z |- _ =>
unless (R x z) by done;
assert (R x z) by (by transitivity y)
end
end.
(** * Sorting *)
(** Merge sort. Adapted from the implementation of Hugo Herbelin in the Coq
standard library, but without using the module system. *)
Section merge_sort.
Context {A} (R : relation A) `{∀ x y, Decision (R x y)}.
Fixpoint list_merge (l1 : list A) : list A → list A :=
fix list_merge_aux l2 :=
match l1, l2 with
| [], _ => l2
| _, [] => l1
| x1 :: l1, x2 :: l2 =>
if decide_rel R x1 x2 then x1 :: list_merge l1 (x2 :: l2)
else x2 :: list_merge_aux l2
end.
Global Arguments list_merge !_ !_ /.
Local Notation stack := (list (option (list A))).
Fixpoint merge_list_to_stack (st : stack) (l : list A) : stack :=
match st with
| [] => [Some l]
| None :: st => Some l :: st
| Some l' :: st => None :: merge_list_to_stack st (list_merge l' l)
end.
Fixpoint merge_stack (st : stack) : list A :=
match st with
| [] => []
| None :: st => merge_stack st
| Some l :: st => list_merge l (merge_stack st)
end.
Fixpoint merge_sort_aux (st : stack) (l : list A) : list A :=
match l with
| [] => merge_stack st
| x :: l => merge_sort_aux (merge_list_to_stack st [x]) l
end.
Definition merge_sort : list A → list A := merge_sort_aux [].
End merge_sort.
(** ** Properties of the [Sorted] and [StronglySorted] predicate *)
Section sorted.
Context {A} (R : relation A).
Lemma Sorted_StronglySorted `{!Transitive R} l :
Sorted R l → StronglySorted R l.
Proof. by apply Sorted.Sorted_StronglySorted. Qed.
Lemma StronglySorted_unique `{!AntiSymmetric (=) R} l1 l2 :
StronglySorted R l1 → StronglySorted R l2 → l1 ≡ₚ l2 → l1 = l2.
Proof.
intros Hl1; revert l2. induction Hl1 as [|x1 l1 ? IH Hx1]; intros l2 Hl2 E.
{ symmetry. by apply Permutation_nil. }
destruct Hl2 as [|x2 l2 ? Hx2].
{ by apply Permutation_nil in E. }
assert (x1 = x2); subst.
{ rewrite Forall_forall in Hx1, Hx2.
assert (x2 ∈ x1 :: l1) as Hx2' by (by rewrite E; left).
assert (x1 ∈ x2 :: l2) as Hx1' by (by rewrite <-E; left).
inversion Hx1'; inversion Hx2'; simplify_equality; auto. }
f_equal. by apply IH, (injective (x2 ::)).
Qed.
Lemma Sorted_unique `{!Transitive R, !AntiSymmetric (=) R} l1 l2 :
Sorted R l1 → Sorted R l2 → l1 ≡ₚ l2 → l1 = l2.
Proof. auto using StronglySorted_unique, Sorted_StronglySorted. Qed.
Global Instance HdRel_dec x `{∀ y, Decision (R x y)} l :
Decision (HdRel R x l).
Proof.
refine
match l with
| [] => left _
| y :: l => cast_if (decide (R x y))
end; abstract first [by constructor | by inversion 1].
Defined.
Global Instance Sorted_dec `{∀ x y, Decision (R x y)} : ∀ l,
Decision (Sorted R l).
Proof.
refine
(fix go l :=
match l return Decision (Sorted R l) with
| [] => left _
| x :: l => cast_if_and (decide (HdRel R x l)) (go l)
end); clear go; abstract first [by constructor | by inversion 1].
Defined.
Global Instance StronglySorted_dec `{∀ x y, Decision (R x y)} : ∀ l,
Decision (StronglySorted R l).
Proof.
refine
(fix go l :=
match l return Decision (StronglySorted R l) with
| [] => left _
| x :: l => cast_if_and (decide (Forall (R x) l)) (go l)
end); clear go; abstract first [by constructor | by inversion 1].
Defined.
Context {B} (f : A → B).
Lemma HdRel_fmap (R1 : relation A) (R2 : relation B) x l :
(∀ y, R1 x y → R2 (f x) (f y)) → HdRel R1 x l → HdRel R2 (f x) (f <$> l).
Proof. destruct 2; constructor; auto. Qed.
Lemma Sorted_fmap (R1 : relation A) (R2 : relation B) l :
(∀ x y, R1 x y → R2 (f x) (f y)) → Sorted R1 l → Sorted R2 (f <$> l).
Proof. induction 2; simpl; constructor; eauto using HdRel_fmap. Qed.
Lemma StronglySorted_fmap (R1 : relation A) (R2 : relation B) l :
(∀ x y, R1 x y → R2 (f x) (f y)) →
StronglySorted R1 l → StronglySorted R2 (f <$> l).
Proof.
induction 2; csimpl; constructor;
rewrite ?Forall_fmap; eauto using Forall_impl.
Qed.
End sorted.
(** ** Correctness of merge sort *)
Section merge_sort_correct.
Context {A} (R : relation A) `{∀ x y, Decision (R x y)} `{!Total R}.
Lemma list_merge_cons x1 x2 l1 l2 :
list_merge R (x1 :: l1) (x2 :: l2) =
if decide (R x1 x2) then x1 :: list_merge R l1 (x2 :: l2)
else x2 :: list_merge R (x1 :: l1) l2.
Proof. done. Qed.
Lemma HdRel_list_merge x l1 l2 :
HdRel R x l1 → HdRel R x l2 → HdRel R x (list_merge R l1 l2).
Proof.
destruct 1 as [|x1 l1 IH1], 1 as [|x2 l2 IH2];
rewrite ?list_merge_cons; simpl; repeat case_decide; auto.
Qed.
Lemma Sorted_list_merge l1 l2 :
Sorted R l1 → Sorted R l2 → Sorted R (list_merge R l1 l2).
Proof.
intros Hl1. revert l2. induction Hl1 as [|x1 l1 IH1];
induction 1 as [|x2 l2 IH2]; rewrite ?list_merge_cons; simpl;
repeat case_decide;
constructor; eauto using HdRel_list_merge, HdRel_cons, total_not.
Qed.
Lemma merge_Permutation l1 l2 : list_merge R l1 l2 ≡ₚ l1 ++ l2.
Proof.
revert l2. induction l1 as [|x1 l1 IH1]; intros l2;
induction l2 as [|x2 l2 IH2]; rewrite ?list_merge_cons; simpl;
repeat case_decide; auto.
* by rewrite (right_id_L [] (++)).
* by rewrite IH2, Permutation_middle.
Qed.
Local Notation stack := (list (option (list A))).
Inductive merge_stack_Sorted : stack → Prop :=
| merge_stack_Sorted_nil : merge_stack_Sorted []
| merge_stack_Sorted_cons_None st :
merge_stack_Sorted st → merge_stack_Sorted (None :: st)
| merge_stack_Sorted_cons_Some l st :
Sorted R l → merge_stack_Sorted st → merge_stack_Sorted (Some l :: st).
Fixpoint merge_stack_flatten (st : stack) : list A :=
match st with
| [] => []
| None :: st => merge_stack_flatten st
| Some l :: st => l ++ merge_stack_flatten st
end.
Lemma Sorted_merge_list_to_stack st l :
merge_stack_Sorted st → Sorted R l →
merge_stack_Sorted (merge_list_to_stack R st l).
Proof.
intros Hst. revert l.
induction Hst; repeat constructor; naive_solver auto using Sorted_list_merge.
Qed.
Lemma merge_list_to_stack_Permutation st l :
merge_stack_flatten (merge_list_to_stack R st l) ≡ₚ
l ++ merge_stack_flatten st.
Proof.
revert l. induction st as [|[l'|] st IH]; intros l; simpl; auto.
by rewrite IH, merge_Permutation, (associative_L _), (commutative (++) l).
Qed.
Lemma Sorted_merge_stack st :
merge_stack_Sorted st → Sorted R (merge_stack R st).
Proof. induction 1; simpl; auto using Sorted_list_merge. Qed.
Lemma merge_stack_Permutation st : merge_stack R st ≡ₚ merge_stack_flatten st.
Proof.
induction st as [|[] ? IH]; intros; simpl; auto.
by rewrite merge_Permutation, IH.
Qed.
Lemma Sorted_merge_sort_aux st l :
merge_stack_Sorted st → Sorted R (merge_sort_aux R st l).
Proof.
revert st. induction l; simpl;
auto using Sorted_merge_stack, Sorted_merge_list_to_stack.
Qed.
Lemma merge_sort_aux_Permutation st l :
merge_sort_aux R st l ≡ₚ merge_stack_flatten st ++ l.
Proof.
revert st. induction l as [|?? IH]; simpl; intros.
* by rewrite (right_id_L [] (++)), merge_stack_Permutation.
* rewrite IH, merge_list_to_stack_Permutation; simpl.
by rewrite Permutation_middle.
Qed.
Lemma Sorted_merge_sort l : Sorted R (merge_sort R l).
Proof. apply Sorted_merge_sort_aux. by constructor. Qed.
Lemma merge_sort_Permutation l : merge_sort R l ≡ₚ l.
Proof. unfold merge_sort. by rewrite merge_sort_aux_Permutation. Qed.
Lemma StronglySorted_merge_sort `{!Transitive R} l :
StronglySorted R (merge_sort R l).
Proof. auto using Sorted_StronglySorted, Sorted_merge_sort. Qed.
End merge_sort_correct.
(** * Canonical pre and partial orders *)
(** We extend the canonical pre-order [⊆] to a partial order by defining setoid
equality as [λ X Y, X ⊆ Y ∧ Y ⊆ X]. We prove that this indeed gives rise to a
setoid. *)
Instance preorder_equiv `{SubsetEq A} : Equiv A := λ X Y, X ⊆ Y ∧ Y ⊆ X.
Section preorder.
Context `{SubsetEq A, !PreOrder (@subseteq A _)}.
Instance preorder_equivalence: @Equivalence A (≡).
Proof.
split.
* done.
* by intros ?? [??].
* by intros X Y Z [??] [??]; split; transitivity Y.
Qed.
Global Instance: Proper ((≡) ==> (≡) ==> iff) (⊆).
Proof.
unfold equiv, preorder_equiv. intros X1 Y1 ? X2 Y2 ?. split; intro.
* transitivity X1. tauto. transitivity X2; tauto.
* transitivity Y1. tauto. transitivity Y2; tauto.
Qed.
Lemma subset_spec X Y : X ⊂ Y ↔ X ⊆ Y ∧ X ≢ Y.
Proof.
split.
* intros [? HYX]. split. done. contradict HYX. by rewrite <-HYX.
* intros [? HXY]. split. done. by contradict HXY.
Qed.
Section dec.
Context `{∀ X Y : A, Decision (X ⊆ Y)}.
Global Instance preorder_equiv_dec_slow (X Y : A) :
Decision (X ≡ Y) | 100 := _.
Lemma subseteq_inv X Y : X ⊆ Y → X ⊂ Y ∨ X ≡ Y.
Proof. rewrite subset_spec. destruct (decide (X ≡ Y)); tauto. Qed.
Lemma not_subset_inv X Y : X ⊄ Y → X ⊈ Y ∨ X ≡ Y.
Proof. rewrite subset_spec. destruct (decide (X ≡ Y)); tauto. Qed.
End dec.
Section leibniz.
Context `{!LeibnizEquiv A}.
Lemma subset_spec_L X Y : X ⊂ Y ↔ X ⊆ Y ∧ X ≠ Y.
Proof. unfold_leibniz. apply subset_spec. Qed.
Context `{∀ X Y : A, Decision (X ⊆ Y)}.
Lemma subseteq_inv_L X Y : X ⊆ Y → X ⊂ Y ∨ X = Y.
Proof. unfold_leibniz. apply subseteq_inv. Qed.
Lemma not_subset_inv_L X Y : X ⊄ Y → X ⊈ Y ∨ X = Y.
Proof. unfold_leibniz. apply not_subset_inv. Qed.
End leibniz.
End preorder.
Typeclasses Opaque preorder_equiv.
Hint Extern 0 (@Equivalence _ (≡)) =>
class_apply preorder_equivalence : typeclass_instances.
(** * Partial orders *)
Section partial_order.
Context `{SubsetEq A, !PartialOrder (@subseteq A _)}.
Global Instance: LeibnizEquiv A.
Proof. split. intros [??]. by apply (anti_symmetric (⊆)). by intros ->. Qed.
End partial_order.
(** * Join semi lattices *)
(** General purpose theorems on join semi lattices. *)
Section join_semi_lattice.
Context `{Empty A, JoinSemiLattice A, !EmptySpec A}.
Implicit Types X Y : A.
Implicit Types Xs Ys : list A.
Hint Resolve subseteq_empty union_subseteq_l union_subseteq_r union_least.
Lemma union_subseteq_l_transitive X1 X2 Y : X1 ⊆ X2 → X1 ⊆ X2 ∪ Y.
Proof. intros. transitivity X2; auto. Qed.
Lemma union_subseteq_r_transitive X1 X2 Y : X1 ⊆ X2 → X1 ⊆ Y ∪ X2.
Proof. intros. transitivity X2; auto. Qed.
Hint Resolve union_subseteq_l_transitive union_subseteq_r_transitive.
Lemma union_preserving_l X Y1 Y2 : Y1 ⊆ Y2 → X ∪ Y1 ⊆ X ∪ Y2.
Proof. auto. Qed.
Lemma union_preserving_r X1 X2 Y : X1 ⊆ X2 → X1 ∪ Y ⊆ X2 ∪ Y.
Proof. auto. Qed.
Lemma union_preserving X1 X2 Y1 Y2 : X1 ⊆ X2 → Y1 ⊆ Y2 → X1 ∪ Y1 ⊆ X2 ∪ Y2.
Proof. auto. Qed.
Lemma union_empty X : X ∪ ∅ ⊆ X.
Proof. by apply union_least. Qed.
Global Instance union_proper : Proper ((≡) ==> (≡) ==> (≡)) (∪).
Proof.
unfold equiv, preorder_equiv.
split; apply union_preserving; simpl in *; tauto.
Qed.
Global Instance: Idempotent (≡) (∪).
Proof. split; eauto. Qed.
Global Instance: LeftId (≡) ∅ (∪).
Proof. split; eauto. Qed.
Global Instance: RightId (≡) ∅ (∪).
Proof. split; eauto. Qed.
Global Instance: Commutative (≡) (∪).
Proof. split; auto. Qed.
Global Instance: Associative (≡) (∪).
Proof. split; auto. Qed.
Lemma subseteq_union X Y : X ⊆ Y ↔ X ∪ Y ≡ Y.
Proof. repeat split; eauto. intros HXY. rewrite <-HXY. auto. Qed.
Lemma subseteq_union_1 X Y : X ⊆ Y → X ∪ Y ≡ Y.
Proof. apply subseteq_union. Qed.
Lemma subseteq_union_2 X Y : X ∪ Y ≡ Y → X ⊆ Y.
Proof. apply subseteq_union. Qed.
Lemma equiv_empty X : X ⊆ ∅ → X ≡ ∅.
Proof. split; eauto. Qed.
Global Instance union_list_proper: Proper (Forall2 (≡) ==> (≡)) union_list.
Proof. induction 1; simpl. done. by apply union_proper. Qed.
Lemma union_list_nil : ⋃ @nil A = ∅.
Proof. done. Qed.
Lemma union_list_cons X Xs : ⋃ (X :: Xs) = X ∪ ⋃ Xs.
Proof. done. Qed.
Lemma union_list_singleton X : ⋃ [X] ≡ X.
Proof. simpl. by rewrite (right_id ∅ _). Qed.
Lemma union_list_app Xs1 Xs2 : ⋃ (Xs1 ++ Xs2) ≡ ⋃ Xs1 ∪ ⋃ Xs2.
Proof.
induction Xs1 as [|X Xs1 IH]; simpl; [by rewrite (left_id ∅ _)|].
by rewrite IH, (associative _).
Qed.
Lemma union_list_reverse Xs : ⋃ (reverse Xs) ≡ ⋃ Xs.
Proof.
induction Xs as [|X Xs IH]; simpl; [done |].
by rewrite reverse_cons, union_list_app,
union_list_singleton, (commutative _), IH.
Qed.
Lemma union_list_preserving Xs Ys : Xs ⊆* Ys → ⋃ Xs ⊆ ⋃ Ys.
Proof. induction 1; simpl; auto using union_preserving. Qed.
Lemma empty_union X Y : X ∪ Y ≡ ∅ ↔ X ≡ ∅ ∧ Y ≡ ∅.
Proof.
split.
* intros HXY. split; apply equiv_empty;
by transitivity (X ∪ Y); [auto | rewrite HXY].
* intros [HX HY]. by rewrite HX, HY, (left_id _ _).
Qed.
Lemma empty_union_list Xs : ⋃ Xs ≡ ∅ ↔ Forall (≡ ∅) Xs.
Proof.
split.
* induction Xs; simpl; rewrite ?empty_union; intuition.
* induction 1 as [|?? E1 ? E2]; simpl. done. by apply empty_union.
Qed.
Section leibniz.
Context `{!LeibnizEquiv A}.
Global Instance: Idempotent (=) (∪).
Proof. intros ?. unfold_leibniz. apply (idempotent _). Qed.
Global Instance: LeftId (=) ∅ (∪).
Proof. intros ?. unfold_leibniz. apply (left_id _ _). Qed.
Global Instance: RightId (=) ∅ (∪).
Proof. intros ?. unfold_leibniz. apply (right_id _ _). Qed.
Global Instance: Commutative (=) (∪).
Proof. intros ??. unfold_leibniz. apply (commutative _). Qed.
Global Instance: Associative (=) (∪).
Proof. intros ???. unfold_leibniz. apply (associative _). Qed.
Lemma subseteq_union_L X Y : X ⊆ Y ↔ X ∪ Y = Y.
Proof. unfold_leibniz. apply subseteq_union. Qed.
Lemma subseteq_union_1_L X Y : X ⊆ Y → X ∪ Y = Y.
Proof. unfold_leibniz. apply subseteq_union_1. Qed.
Lemma subseteq_union_2_L X Y : X ∪ Y = Y → X ⊆ Y.
Proof. unfold_leibniz. apply subseteq_union_2. Qed.
Lemma equiv_empty_L X : X ⊆ ∅ → X = ∅.
Proof. unfold_leibniz. apply equiv_empty. Qed.
Lemma union_list_singleton_L (X : A) : ⋃ [X] = X.
Proof. unfold_leibniz. apply union_list_singleton. Qed.
Lemma union_list_app_L (Xs1 Xs2 : list A) : ⋃ (Xs1 ++ Xs2) = ⋃ Xs1 ∪ ⋃ Xs2.
Proof. unfold_leibniz. apply union_list_app. Qed.
Lemma union_list_reverse_L (Xs : list A) : ⋃ (reverse Xs) = ⋃ Xs.
Proof. unfold_leibniz. apply union_list_reverse. Qed.
Lemma empty_union_L X Y : X ∪ Y = ∅ ↔ X = ∅ ∧ Y = ∅.
Proof. unfold_leibniz. apply empty_union. Qed.
Lemma empty_union_list_L Xs : ⋃ Xs = ∅ ↔ Forall (= ∅) Xs.
Proof. unfold_leibniz. by rewrite empty_union_list. Qed.
End leibniz.
Section dec.
Context `{∀ X Y : A, Decision (X ⊆ Y)}.
Lemma non_empty_union X Y : X ∪ Y ≢ ∅ ↔ X ≢ ∅ ∨ Y ≢ ∅.
Proof. rewrite empty_union. destruct (decide (X ≡ ∅)); intuition. Qed.
Lemma non_empty_union_list Xs : ⋃ Xs ≢ ∅ → Exists (≢ ∅) Xs.
Proof. rewrite empty_union_list. apply (not_Forall_Exists _). Qed.
Context `{!LeibnizEquiv A}.
Lemma non_empty_union_L X Y : X ∪ Y ≠ ∅ ↔ X ≠ ∅ ∨ Y ≠ ∅.
Proof. unfold_leibniz. apply non_empty_union. Qed.
Lemma non_empty_union_list_L Xs : ⋃ Xs ≠ ∅ → Exists (≠ ∅) Xs.
Proof. unfold_leibniz. apply non_empty_union_list. Qed.
End dec.
End join_semi_lattice.
(** * Meet semi lattices *)
(** The dual of the above section, but now for meet semi lattices. *)
Section meet_semi_lattice.
Context `{MeetSemiLattice A}.
Implicit Types X Y : A.
Implicit Types Xs Ys : list A.
Hint Resolve intersection_subseteq_l intersection_subseteq_r
intersection_greatest.
Lemma intersection_subseteq_l_transitive X1 X2 Y : X1 ⊆ X2 → X1 ∩ Y ⊆ X2.
Proof. intros. transitivity X1; auto. Qed.
Lemma intersection_subseteq_r_transitive X1 X2 Y : X1 ⊆ X2 → Y ∩ X1 ⊆ X2.
Proof. intros. transitivity X1; auto. Qed.
Hint Resolve intersection_subseteq_l_transitive
intersection_subseteq_r_transitive.
Lemma intersection_preserving_l X Y1 Y2 : Y1 ⊆ Y2 → X ∩ Y1 ⊆ X ∩ Y2.
Proof. auto. Qed.
Lemma intersection_preserving_r X1 X2 Y : X1 ⊆ X2 → X1 ∩ Y ⊆ X2 ∩ Y.
Proof. auto. Qed.
Lemma intersection_preserving X1 X2 Y1 Y2 :
X1 ⊆ X2 → Y1 ⊆ Y2 → X1 ∩ Y1 ⊆ X2 ∩ Y2.
Proof. auto. Qed.
Global Instance: Proper ((≡) ==> (≡) ==> (≡)) (∩).
Proof.
unfold equiv, preorder_equiv. split;
apply intersection_preserving; simpl in *; tauto.
Qed.
Global Instance: Idempotent (≡) (∩).
Proof. split; eauto. Qed.
Global Instance: Commutative (≡) (∩).
Proof. split; auto. Qed.
Global Instance: Associative (≡) (∩).
Proof. split; auto. Qed.
Lemma subseteq_intersection X Y : X ⊆ Y ↔ X ∩ Y ≡ X.
Proof. repeat split; eauto. intros HXY. rewrite <-HXY. auto. Qed.
Lemma subseteq_intersection_1 X Y : X ⊆ Y → X ∩ Y ≡ X.
Proof. apply subseteq_intersection. Qed.
Lemma subseteq_intersection_2 X Y : X ∩ Y ≡ X → X ⊆ Y.
Proof. apply subseteq_intersection. Qed.
Section leibniz.
Context `{!LeibnizEquiv A}.
Global Instance: Idempotent (=) (∩).
Proof. intros ?. unfold_leibniz. apply (idempotent _). Qed.
Global Instance: Commutative (=) (∩).
Proof. intros ??. unfold_leibniz. apply (commutative _). Qed.
Global Instance: Associative (=) (∩).
Proof. intros ???. unfold_leibniz. apply (associative _). Qed.
Lemma subseteq_intersection_L X Y : X ⊆ Y ↔ X ∩ Y = X.
Proof. unfold_leibniz. apply subseteq_intersection. Qed.
Lemma subseteq_intersection_1_L X Y : X ⊆ Y → X ∩ Y = X.
Proof. unfold_leibniz. apply subseteq_intersection_1. Qed.
Lemma subseteq_intersection_2_L X Y : X ∩ Y = X → X ⊆ Y.
Proof. unfold_leibniz. apply subseteq_intersection_2. Qed.
End leibniz.
End meet_semi_lattice.
(** * Lower bounded lattices *)
Section lattice.
Context `{Empty A, Lattice A, !EmptySpec A}.
Global Instance: LeftAbsorb (≡) ∅ (∩).
Proof. split. by apply intersection_subseteq_l. by apply subseteq_empty. Qed.
Global Instance: RightAbsorb (≡) ∅ (∩).
Proof. intros ?. by rewrite (commutative _), (left_absorb _ _). Qed.
Global Instance: LeftDistr (≡) (∪) (∩).
Proof.
intros X Y Z. split; [|apply lattice_distr].
apply union_least.
{ apply intersection_greatest; auto using union_subseteq_l. }
apply intersection_greatest.
* apply union_subseteq_r_transitive, intersection_subseteq_l.
* apply union_subseteq_r_transitive, intersection_subseteq_r.
Qed.
Global Instance: RightDistr (≡) (∪) (∩).
Proof. intros X Y Z. by rewrite !(commutative _ _ Z), (left_distr _ _). Qed.
Global Instance: LeftDistr (≡) (∩) (∪).
Proof.
intros X Y Z. split.
* rewrite (left_distr (∪) (∩)).
apply intersection_greatest.
{ apply union_subseteq_r_transitive, intersection_subseteq_l. }
rewrite (right_distr (∪) (∩)).
apply intersection_preserving; auto using union_subseteq_l.
* apply intersection_greatest.
{ apply union_least; auto using intersection_subseteq_l. }
apply union_least.
+ apply intersection_subseteq_r_transitive, union_subseteq_l.
+ apply intersection_subseteq_r_transitive, union_subseteq_r.
Qed.
Global Instance: RightDistr (≡) (∩) (∪).
Proof. intros X Y Z. by rewrite !(commutative _ _ Z), (left_distr _ _). Qed.
Section leibniz.
Context `{!LeibnizEquiv A}.
Global Instance: LeftAbsorb (=) ∅ (∩).
Proof. intros ?. unfold_leibniz. apply (left_absorb _ _). Qed.
Global Instance: RightAbsorb (=) ∅ (∩).
Proof. intros ?. unfold_leibniz. apply (right_absorb _ _). Qed.
Global Instance: LeftDistr (=) (∪) (∩).
Proof. intros ???. unfold_leibniz. apply (left_distr _ _). Qed.
Global Instance: RightDistr (=) (∪) (∩).
Proof. intros ???. unfold_leibniz. apply (right_distr _ _). Qed.
Global Instance: LeftDistr (=) (∩) (∪).
Proof. intros ???. unfold_leibniz. apply (left_distr _ _). Qed.
Global Instance: RightDistr (=) (∩) (∪).
Proof. intros ???. unfold_leibniz. apply (right_distr _ _). Qed.
End leibniz.
End lattice.