Require Import Vbase Relations List Permutation Sorting MMergesort.
Require Import ClassicalDescription.
Set Implicit Arguments.
Require Import ClassicalDescription.
Set Implicit Arguments.
This file contains a number of basic definitions and lemmas about lists
that are missing from the standard library, and a few properties of
classical logic.
Very basic lemmas
Definition appA := app_ass.
Lemma in_cons_iff A (a b : A) l : In b (a :: l) ↔ a = b ∨ In b l.
Proof. done. Qed.
Lemma In_split2 :
∀ A (x: A) l (IN: In x l),
∃ l1 l2, l = l1 ++ x :: l2 ∧ ¬ In x l1.
Proof.
induction l; ins; desf; [by eexists nil; ins; eauto|].
destruct (classic (a = x)); desf; [by eexists nil; ins; eauto|].
apply IHl in IN; desf; eexists (_ :: _),,; ins; intro; desf.
Qed.
Lemma map_eq_app_inv A B (f : A → B) l l1 l2 :
map f l = l1 ++ l2 →
∃ l1' l2', l = l1' ++ l2' ∧ map f l1' = l1 ∧ map f l2' = l2.
Proof.
induction[l1] l; ins.
by destruct l1, l2; ins; eexists nil, nil.
destruct l1; ins; desf.
by eexists nil,,; ins.
eapply IHl in H; desf; eexists (_ :: _),,; ins.
Qed.
List filtering
Lemma in_filter_iff A l f (x : A) : In x (filter f l) ↔ In x l ∧ f x.
Proof.
induction l; ins; try tauto.
des_if; ins; rewrite IHl; split; ins; desf; eauto.
Qed.
Lemma filter_app A f (l l' : list A) :
filter f (l ++ l') = filter f l ++ filter f l'.
Proof.
induction l; ins; desf; ins; congruence.
Qed.
List flattening
Fixpoint flatten A (l: list (list A)) :=
match l with
| nil ⇒ nil
| x :: l' ⇒ x ++ flatten l'
end.
Lemma in_flatten_iff A (x: A) ll :
In x (flatten ll) ↔ ∃ l, In l ll ∧ In x l.
Proof.
induction ll; ins.
by split; ins; desf.
rewrite in_app_iff, IHll; clear; split; ins; desf; eauto.
Qed.
List disjointness
Remove duplicate list elements (classical)
Fixpoint undup A (l: list A) :=
match l with nil ⇒ nil
| x :: l ⇒
if excluded_middle_informative (In x l) then undup l else x :: undup l
end.
Lemma nodup_one A (x: A) : NoDup (x :: nil).
Proof. vauto. Qed.
Hint Resolve NoDup_nil nodup_one.
Lemma nodup_map:
∀ (A B: Type) (f: A → B) (l: list A),
NoDup l →
(∀ x y, In x l → In y l → x ≠ y → f x ≠ f y) →
NoDup (map f l).
Proof.
induction 1; ins; vauto.
constructor; eauto.
intro; rewrite in_map_iff in *; desf.
edestruct H1; try eapply H2; eauto.
intro; desf.
Qed.
Lemma nodup_append_commut:
∀ (A: Type) (a b: list A),
NoDup (a ++ b) → NoDup (b ++ a).
Proof.
intro A.
assert (∀ (x: A) (b: list A) (a: list A),
NoDup (a ++ b) → ~(In x a) → ~(In x b) →
NoDup (a ++ x :: b)).
induction a; simpl; intros.
constructor; auto.
inversion H. constructor. red; intro.
elim (in_app_or _ _ _ H6); intro.
elim H4. apply in_or_app. tauto.
elim H7; intro. subst a. elim H0. left. auto.
elim H4. apply in_or_app. tauto.
auto.
induction a; simpl; intros.
rewrite <- app_nil_end. auto.
inversion H0. apply H. auto.
red; intro; elim H3. apply in_or_app. tauto.
red; intro; elim H3. apply in_or_app. tauto.
Qed.
Lemma nodup_cons A (x: A) l:
NoDup (x :: l) ↔ ¬ In x l ∧ NoDup l.
Proof. split; inversion 1; vauto. Qed.
Lemma nodup_app:
∀ (A: Type) (l1 l2: list A),
NoDup (l1 ++ l2) ↔
NoDup l1 ∧ NoDup l2 ∧ disjoint l1 l2.
Proof.
induction l1; ins.
by split; ins; desf; vauto.
rewrite !nodup_cons, IHl1, in_app_iff; unfold disjoint.
ins; intuition (subst; eauto).
Qed.
Lemma nodup_append:
∀ (A: Type) (l1 l2: list A),
NoDup l1 → NoDup l2 → disjoint l1 l2 →
NoDup (l1 ++ l2).
Proof.
generalize nodup_app; firstorder.
Qed.
Lemma nodup_append_right:
∀ (A: Type) (l1 l2: list A),
NoDup (l1 ++ l2) → NoDup l2.
Proof.
generalize nodup_app; firstorder.
Qed.
Lemma nodup_append_left:
∀ (A: Type) (l1 l2: list A),
NoDup (l1 ++ l2) → NoDup l1.
Proof.
generalize nodup_app; firstorder.
Qed.
Lemma nodup_filter A (l: list A) (ND: NoDup l) f : NoDup (filter f l).
Proof.
induction l; ins; inv ND; desf; eauto using NoDup.
econstructor; eauto; rewrite in_filter_iff; tauto.
Qed.
Hint Resolve nodup_filter.
Lemma Permutation_nodup A ( l l' : list A) :
Permutation l l' → NoDup l → NoDup l'.
Proof.
induction 1; eauto; rewrite !nodup_cons in *; ins; desf; intuition.
eby symmetry in H; eapply H0; eapply Permutation_in.
Qed.
Lemma nodup_eq_one A (x : A) l :
NoDup l → In x l → (∀ y (IN: In y l), y = x) → l = x :: nil.
Proof.
destruct l; ins; f_equal; eauto.
inv H; desf; clear H H5; induction l; ins; desf; case H4; eauto using eq_sym.
rewrite IHl in H0; ins; desf; eauto.
Qed.
Lemma nodup_consD A (x : A) l : NoDup (x :: l) → NoDup l.
Proof. inversion 1; desf. Qed.
Lemma nodup_mapD A B (f : A→ B) l : NoDup (map f l) → NoDup l.
Proof.
induction l; ins; rewrite !nodup_cons, in_map_iff in *; desf; eauto 8.
Qed.
Lemma In_NoDup_Permutation A (a : A) l (IN: In a l) (ND : NoDup l) :
∃ l', Permutation l (a :: l') ∧ ¬ In a l'.
Proof.
induction l; ins; desf; inv ND; eauto.
destruct IHl as (l' & ? & ?); eauto.
destruct (classic (a0 = a)); desf.
eexists (a0 :: l'); split; try red; ins; desf.
eapply Permutation_trans, perm_swap; eauto.
Qed.
Lemma in_undup_iff A (x : A) (l : list A) : In x (undup l) ↔ In x l.
Proof. induction l; split; ins; desf; ins; desf; eauto. Qed.
Lemma nodup_undup A (l : list A) : NoDup (undup l).
Proof. induction l; ins; desf; constructor; rewrite ?in_undup_iff in *; eauto. Qed.
Hint Resolve nodup_undup.
Lemma undup_nodup A (l : list A) : NoDup l → undup l = l.
Proof. induction 1; ins; desf; congruence. Qed.
Lemma Sorted_undup A p (l : list A) :
StronglySorted p l → StronglySorted p (undup l).
Proof.
induction 1; ins; desf; constructor; eauto.
rewrite Forall_forall in *; ins; rewrite in_undup_iff in *; eauto.
Qed.
Lemma undup_nonnil A (l : list A) : l ≠ nil → undup l ≠ nil.
Proof.
induction l; ins; desf.
by eapply in_undup_iff in i; intro X; rewrite X in ×.
Qed.
Lemma Permutation_undup A (l l' : list A) :
Permutation l l' → Permutation (undup l) (undup l').
Proof.
ins; eapply NoDup_Permutation; ins; rewrite !in_undup_iff.
split; eauto using Permutation_in, Permutation_sym.
Qed.
Function update
Definition upd A B (f : A → B) a b x :=
if excluded_middle_informative (x = a) then b else f x.
Lemma upds A B (f: A → B) a b : upd f a b a = b.
Proof. unfold upd; desf. Qed.
Lemma updo A B (f: A → B) a b c (NEQ: c ≠ a) : upd f a b c = f c.
Proof. unfold upd; desf. Qed.
Ltac rupd := repeat first [rewrite upds | rewrite updo ; try done].
Lemma updss A B (f : A → B) l x y : upd (upd f l x) l y = upd f l y.
Proof.
extensionality z; unfold upd; desf.
Qed.
Lemma updC A l l' (NEQ: l ≠ l') B (f : A → B) x y :
upd (upd f l x) l' y = upd (upd f l' y) l x.
Proof.
extensionality z; unfold upd; desf.
Qed.
Lemma updI A B (f : A → B) a : upd f a (f a) = f.
Proof.
extensionality a'; unfold upd; desf.
Qed.
Lemma map_upd_irr A (a: A) l (NIN: ¬ In a l) B f (b : B) :
map (upd f a b) l = map f l.
Proof.
unfold upd; induction l; ins.
apply not_or_and in NIN; desf; f_equal; eauto.
Qed.
Decidable function update
Definition mupd (A: eqType) B (h : A → B) y z :=
fun x ⇒ if x == y then z else h x.
Arguments mupd [A B] h y z x.
Lemma mupds (A: eqType) B (f: A → B) x y : mupd f x y x = y.
Proof. by unfold mupd; desf; desf. Qed.
Lemma mupdo (A: eqType) B (f: A → B) x y z : x ≠ z → mupd f x y z = f z.
Proof. by unfold mupd; desf; desf. Qed.
Lemmas about sorting
Lemma sorted_perm_eq : ∀ A (cmp: A → A → Prop)
(TRANS: transitive _ cmp)
(ANTIS: antisymmetric _ cmp)
l l' (P: Permutation l l')
(S : StronglySorted cmp l) (S' : StronglySorted cmp l'), l = l'.
Proof.
induction l; ins.
by apply Permutation_nil in P; desf.
assert (X: In a l') by eauto using Permutation_in, Permutation_sym, in_eq.
apply In_split2 in X; desf; apply Permutation_cons_app_inv in P.
destruct l1; ins; [by inv S; inv S'; eauto using f_equal|].
assert (X: In a0 l) by eauto using Permutation_in, Permutation_sym, in_eq.
inv S; inv S'; rewrite Forall_forall in *; ins.
destruct X0; left; apply ANTIS; eauto using in_eq, in_or_app.
Qed.
Lemma perm_sort_eq A (l l': list A) (P: Permutation l l') cmp
(TOTAL: ∀ x y, In x l → In y l → cmp x y = true ∨ cmp y x = true)
(TRANS: transitive _ cmp)
(ANTIS: antisymmetric _ cmp) :
sort cmp l = sort cmp l'.
Proof.
exploit (@sort_sorted A cmp l); eauto.
exploit (@sort_sorted A cmp l');
eauto 6 using Permutation_in, Permutation_sym.
ins; eauto using sorted_perm_eq, sort_perm, Permutation_trans,
Permutation_sym.
Qed.
Lemma In_sort A (x: A) cmp l : In x (sort cmp l) ↔ In x l.
Proof.
split; eauto using Permutation_in, sort_perm, Permutation_sym.
Qed.
Lemma NoDup_sort A cmp (l : list A) : NoDup (sort cmp l) ↔ NoDup l.
Proof.
split; eauto using Permutation_nodup, Permutation_sym, sort_perm.
Qed.
Lemma NoDup_sort1 A cmp (l : list A) : NoDup l → NoDup (sort cmp l).
Proof.
apply NoDup_sort.
Qed.
Hint Resolve NoDup_sort1.
Lemma Sorted_total :
∀ A cmp (R: reflexive _ cmp) (l: list A), StronglySorted cmp l →
∀ x y, In x l → In y l →
cmp x y ∨ cmp y x.
Proof.
induction 2; ins; rewrite Forall_forall in *; desf; desf; eauto.
Qed.
Lemma Sorted_app_end_inv A (cmp : A → A → Prop) l x :
StronglySorted cmp (l ++ x :: nil) →
∀ y, In y l → cmp y x.
Proof.
ins; induction l; ins; inv H; rewrite Forall_forall in ×.
desf; eauto using in_or_app, in_eq.
Qed.
Fixpoint dprod A B al (f : A → list B) :=
match al with
| nil ⇒ nil
| a :: al ⇒ map (fun b ⇒ (a, b)) (f a) ++ dprod al f
end.
Lemma in_dprod_iff A B x al (f : A → list B) :
In x (dprod al f) ↔ In (fst x) al ∧ In (snd x) (f (fst x)).
Proof.
induction al; ins; rewrite ?in_app_iff, ?in_map_iff, ?IHal; try clear IHal;
split; ins; desf; ins; eauto; destruct x; ins; eauto.
Qed.
Miscellaneous
Lemma perm_from_subset :
∀ A (l : list A) l',
NoDup l' →
(∀ x, In x l' → In x l) →
∃ l'', Permutation l (l' ++ l'').
Proof.
induction l; ins; vauto.
by destruct l'; ins; vauto; exfalso; eauto.
destruct (classic (In a l')).
eapply In_split in H1; desf; rewrite ?nodup_app, ?nodup_cons in *; desf.
destruct (IHl (l1 ++ l2)); ins.
by rewrite ?nodup_app, ?nodup_cons in *; desf; repeat split; ins; red;
eauto using in_cons.
by specialize (H0 x); rewrite in_app_iff in *; ins; desf;
destruct (classic (a = x)); subst; try tauto; exfalso; eauto using in_eq.
eexists; rewrite app_ass in *; ins.
by eapply Permutation_trans, Permutation_middle; eauto.
destruct (IHl l'); eauto; ins.
by destruct (H0 x); auto; ins; subst.
by eexists (a :: _); eapply Permutation_trans, Permutation_middle; eauto.
Qed.
Lemma seq_split_gen :
∀ l n a,
n ≤ a < n + l →
seq n l = seq n (a - n) ++ a :: seq (S a) (l + n - a - 1).
Proof.
induction l; ins; desf; ins; try omega.
repeat f_equal; omega.
destruct (eqP n (S n0)); subst.
replace (n0 - n0) with 0 by omega; ins; repeat f_equal; omega.
rewrite IHl with (a := S n0); try omega.
desf; ins; try replace (n0 - n2) with (S (n0 - S n2)) by omega;
ins; repeat (f_equal; try omega).
Qed.
Lemma seq_split0 :
∀ l a,
a < l →
seq 0 l = seq 0 a ++ a :: seq (S a) (l - a - 1).
Proof.
ins; rewrite seq_split_gen with (a := a); repeat f_equal; omega.
Qed.
Lemma list_prod_app A (l l' : list A) B (m : list B) :
list_prod (l ++ l') m = list_prod l m ++ list_prod l' m.
Proof.
by induction l; ins; rewrite IHl, app_assoc.
Qed.
Lemma list_prod_nil_r A (l : list A) B :
list_prod l (@nil B) = nil.
Proof.
induction l; ins.
Qed.
Lemma list_prod_cons_r A (l : list A) B a (m : list B) :
Permutation (list_prod l (a :: m)) (map (fun x ⇒ (x,a)) l ++ list_prod l m).
Proof.
induction l; ins.
eapply Permutation_cons.
eapply Permutation_trans; [by apply Permutation_app; eauto|].
rewrite !app_assoc; eauto using Permutation_app, Permutation_app_comm.
Qed.
Lemma list_prod_app_r A (l : list A) B (m m' : list B) :
Permutation (list_prod l (m ++ m')) (list_prod l m ++ list_prod l m').
Proof.
induction m; ins; ins.
by rewrite list_prod_nil_r.
rewrite list_prod_cons_r.
eapply Permutation_trans; [by eapply Permutation_app, IHm|].
rewrite app_assoc; apply Permutation_app; ins.
symmetry; apply list_prod_cons_r.
Qed.
Lemma in_seq_iff a n l : In a (seq n l) ↔ n ≤ a < n + l.
Proof.
induction[n] l; ins; rewrite ?IHl; omega.
Qed.
Lemma in_seq0_iff x a : In x (seq 0 a) ↔ x < a.
Proof.
rewrite in_seq_iff; omega.
Qed.
Lemma nodup_seq n l : NoDup (seq n l).
Proof.
induction[n] l; ins; constructor; ins; eauto.
rewrite in_seq_iff; omega.
Qed.
Lemma seq_split :
∀ l a,
a < l →
∃ l', Permutation (seq 0 l) (a :: l') ∧ ¬ In a l'.
Proof.
ins; eapply In_NoDup_Permutation; eauto using nodup_seq; apply in_seq_iff; omega.
Qed.
Lemma Permutation_listprod_r A (l : list A) B (m m' : list B) :
Permutation m m' →
Permutation (list_prod l m) (list_prod l m').
Proof.
ins; revert l; induction H; ins; eauto using Permutation.
by rewrite ?list_prod_cons_r; eauto using Permutation_app.
rewrite list_prod_cons_r.
eapply Permutation_trans; [by apply Permutation_app, list_prod_cons_r|].
symmetry.
rewrite list_prod_cons_r.
eapply Permutation_trans; [by apply Permutation_app, list_prod_cons_r|].
rewrite !app_assoc; eauto using Permutation_app, Permutation_app_comm.
Qed.
Ltac in_simp :=
try match goal with |- ¬ _ ⇒ intro end;
repeat first [
rewrite in_flatten_iff in *; desc; clarify |
rewrite in_map_iff in *; desc; clarify |
rewrite in_seq0_iff in *; desc; clarify ].
Global Opaque seq.
This page has been generated by coqdoc