Require Import List Permutation Equivalence EquivDec Morphisms.
Require Import LibUtils BasicUtils ListAdd.
Import ListNotations.
Local Open Scope list_scope.
Section quotient.
Context {
A}
R {
equiv:
Equivalence R} {
dec:
EqDec A R}.
Fixpoint add_to_bucket (
x:
A) (
ll:
list (
list A)) :
list (
list A)
:=
match ll with
| [] => [[
x]]
|
nil::
ll' =>
add_to_bucket x ll'
| (
y::
l)::
ll' =>
match x ==
y with
|
left _ => (
x::
y::
l)::
ll'
|
right_ => (
y::
l)::(
add_to_bucket x ll')
end
end.
Fixpoint quotient (
l:
list A) :
list (
list A)
:=
match l with
|
nil =>
nil
|
x::
l' =>
let q' :=
quotient l'
in
add_to_bucket x q'
end.
Lemma add_to_bucket_perm a l :
Permutation (
concat (
add_to_bucket a l)) (
a::
concat l).
Proof.
Lemma unquotient_quotient l :
Permutation (
concat (
quotient l))
l.
Proof.
Corollary quotient_in x l :
In x l ->
exists l',
In l' (
quotient l) /\
In x l'.
Proof.
Corollary in_quotient x l l' :
In l' (
quotient l) /\
In x l' ->
In x l.
Proof.
Definition is_equiv_class (
l:
list A) :=
ForallPairs R l.
Definition all_equivs (
l:
list (
list A)) :=
Forall (
is_equiv_class)
l.
Lemma all_equivs_nil :
all_equivs nil.
Proof.
now red.
Qed.
Lemma add_to_bucket_all_equivs a l :
all_equivs l ->
all_equivs (
add_to_bucket a l).
Proof.
unfold all_equivs,
is_equiv_class,
is_equiv_class,
ForallPairs.
induction l;
simpl;
intros isp.
- (
repeat constructor);
simpl ;
intros ;
intuition.
subst ;
reflexivity.
-
invcs isp.
specialize (
IHl H2).
match_destr.
match_destr.
+
constructor;
trivial;
intros.
simpl in *.
intuition;
subst;
trivial.
*
reflexivity.
*
rewrite e ;
auto.
*
rewrite <-
e;
reflexivity.
*
rewrite e;
auto.
+
constructor;
trivial.
Qed.
Lemma quotient_all_equivs l :
all_equivs (
quotient l).
Proof.
Hint Resolve all_equivs_nil : ml.
Hint Resolve add_to_bucket_all_equivs : ml.
induction l; simpl; auto with ml.
Qed.
Hint Resolve quotient_all_equivs :
ml.
Definition different_buckets l1 l2 :=
forall x y,
In x l1 ->
In y l2 -> ~
R x y.
Definition all_different l :=
ForallOrdPairs different_buckets l.
Lemma all_different_nil :
all_different nil.
Proof.
constructor.
Qed.
Lemma add_to_buckets_in_one {
x a l} :
In x (
add_to_bucket a l) ->
In a x \/
In x l.
Proof.
induction l; simpl; intros inn.
- destruct inn as [inn|inn]; [ | intuition].
invcs inn ; simpl ; intuition.
- match_destr_in inn.
+ intuition.
+ match_destr_in inn
; simpl in inn.
* destruct inn as [inn|inn].
-- invcs inn.
simpl ; eauto.
-- eauto.
* intuition.
Qed.
Lemma add_to_bucket_all_different a l :
all_equivs l ->
all_different l ->
all_different (
add_to_bucket a l).
Proof.
unfold all_different.
induction l;
simpl.
-
repeat constructor.
-
intros isp ordp;
invcs isp;
invcs ordp.
specialize (
IHl H2 H4).
match_destr.
match_destr.
+
constructor;
trivial.
revert H3.
apply Forall_impl;
intros.
red in e.
unfold different_buckets in *;
simpl in *.
intuition;
subst;
eauto 3.
*
eapply H;
eauto.
now rewrite <-
e.
+
constructor;
trivial.
rewrite Forall_forall;
intros.
generalize (
add_to_bucket_all_equivs a l H2);
intros.
red in H0.
eapply Forall_forall in H0;
eauto.
repeat red in H0.
destruct (
add_to_buckets_in_one H).
*
red;
simpl;
intros.
rewrite (
H0 _ _ H7 H5).
destruct H6.
--
subst.
intuition.
--
repeat red in H1.
rewrite (
H1 x0 a0);
simpl;
intuition.
*
eapply Forall_forall in H3;
eauto.
Qed.
Hint Resolve all_different_nil :
ml.
Hint Resolve add_to_bucket_all_different :
ml.
Lemma quotient_all_different l :
all_different (
quotient l).
Proof.
induction l ; simpl ; auto with ml.
Qed.
Hint Resolve quotient_all_different :
ml.
Definition is_partition l :=
all_equivs l /\
all_different l.
Lemma quotient_partitions l :
is_partition (
quotient l).
Proof.
red; auto with ml.
Qed.
Hint Resolve quotient_partitions :
ml.
Definition preserves_partitions (
f:
list (
list A)->
list (
list A))
:=
forall (
l:
list (
list A)),
is_partition l ->
is_partition (
f l).
Lemma filter_preserves_partitions (
p:
list A ->
bool) :
preserves_partitions (
filter p).
Proof.
Lemma add_to_bucket_is_partition a :
preserves_partitions (
add_to_bucket a).
Proof.
Lemma quotient_buckets_disjoint_app l ll1 ll2 :
quotient l =
ll1 ++
ll2 ->
forall l1 l2 x y,
In l1 ll1 ->
In l2 ll2 ->
In x l1 ->
In y l2 -> ~
R x y.
Proof.
Lemma quotient_buckets_disjoint_cons l ll1 l2 ll3 l4 ll5 :
quotient l =
ll1 ++
l2 ::
ll3 ++
l4 ::
ll5 ->
forall x y,
In x l2 ->
In y l4 -> ~
R x y.
Proof.
Lemma Forall_map_filter (
l :
list(
list A)) (
p :
A ->
bool) :
Forall (
is_equiv_class)
l ->
Forall (
is_equiv_class) (
map (
filter p)
l).
Proof.
intros H.
induction l.
-
simpl ;
constructor.
-
simpl.
constructor.
+
invcs H.
specialize (
IHl H3).
revert IHl.
rewrite Forall_forall.
intro IHl.
specialize (
IHl a).
intros a0 b Ha0 Hb.
apply filter_In in Ha0.
apply filter_In in Hb.
intuition.
+
invcs H.
specialize (
IHl H3).
assumption.
Qed.
Lemma ForallOrdPairs_map_filter (
l :
list(
list A)) (
p :
A ->
bool):
ForallOrdPairs (
different_buckets)
l ->
ForallOrdPairs (
different_buckets) (
map (
filter p)
l).
Proof.
Lemma map_filter_preserves_partitions (
p:
A ->
bool) :
preserves_partitions (
map (
filter p)).
Proof.
End quotient.
Section more_quotient.
Lemma add_to_bucket_filter_nil {
A} {
R0} {
equiv:
Equivalence R0} {
dec:
EqDec A R0} (
l :
list (
list A)) (
a:
A) :
add_to_bucket R0 a (
filter_nil l) =
filter_nil (
add_to_bucket R0 a l).
Proof.
induction l.
- simpl. reflexivity.
- simpl. destruct a0.
simpl; trivial.
simpl. match_destr. simpl. rewrite IHl.
reflexivity.
Qed.
Lemma filter_nil_quotient {
A}
R {
equiv:
Equivalence R} {
dec:
EqDec A R} (
l:
list A) :
filter_nil (
quotient R l) =
quotient R l.
Proof.
Lemma add_to_bucket_nnil {
A} {
R0} {
equiv:
Equivalence R0} {
dec:
EqDec A R0} (
l :
list (
list A)) (
a:
A) :
Forall (
fun x =>
not_nil x =
true)
l ->
Forall (
fun x =>
not_nil x =
true) (
add_to_bucket R0 a l).
Proof.
induction l;
simpl;
intros HH.
-
eauto.
-
invcs HH.
destruct a0;
simpl; [
eauto | ].
destruct (
equiv_dec a a0);
simpl;
eauto.
Qed.
Lemma quotient_nnil {
A}
R {
equiv:
Equivalence R} {
dec:
EqDec A R} (
l:
list A) :
Forall (
fun x =>
not_nil x =
true) (
quotient R l).
Proof.
Lemma is_partition_cons_inv {
A} {
R} {
x:
list A} {
l} :
is_partition R (
x ::
l) ->
is_partition R l.
Proof.
intros [HH1 HH2]; red.
invcs HH1; invcs HH2.
auto.
Qed.
Global Instance filter_nil_perm_proper {
A} :
Proper ((@
Permutation (
list A)) ==> (@
Permutation (
list A))) (@
filter_nil A).
Proof.
Global Instance all_equivs_perm {
A}
R :
Proper (@
Permutation (
list A) ==>
iff) (
all_equivs R).
Proof.
unfold all_equivs;
intros l1 l2 perm.
rewrite perm.
intuition.
Qed.
Global Instance different_buckets_symmetric {
A} (
R:
A->
A->
Prop) {
sym:
Symmetric R} :
Symmetric (
different_buckets R).
Proof.
Global Instance all_different_perm {
A}
R {
equiv:
Equivalence R} :
Proper (@
Permutation (
list A) ==>
iff) (
all_different R).
Proof.
unfold all_different;
intros HH1 HH2 perm.
rewrite perm.
intuition.
Qed.
Global Instance is_partition_perm {
A}
R {
equiv:
Equivalence R} :
Proper (@
Permutation (
list A) ==>
iff) (
is_partition R).
Proof.
unfold is_partition;
intros l l1 perm.
repeat rewrite perm.
intuition.
Qed.
Lemma add_to_bucket_perm_preserved {
A}
R {
equiv:
Equivalence R} {
dec:
EqDec A R}
x l l' :
Permutation l l' ->
is_partition R l ->
Permutation (
filter_nil (
add_to_bucket R x l)) (
filter_nil (
add_to_bucket R x l')).
Proof.
Hint Resolve is_partition_cons_inv :
ml.
cut (
forall l l' :
list (
list A),
Permutation l l' ->
(
fun l l' => (
is_partition R l ->
Permutation (
filter_nil (
add_to_bucket R x l)) (
filter_nil (
add_to_bucket R x l'))))
l l')
; [
intuition | ].
apply Permutation_ind_bis;
simpl;
intros.
-
trivial.
-
destruct x0.
+
apply H0;
eauto with ml.
+
destruct (
equiv_dec x a);
simpl.
*
now rewrite H.
*
rewrite H0;
eauto with ml.
-
destruct y;
simpl.
+
destruct x0;
simpl.
*
apply H0;
eauto with ml.
*
destruct (
equiv_dec x a);
simpl.
--
now rewrite H.
--
rewrite H0;
eauto with ml.
+
destruct (
equiv_dec x a);
simpl.
--
destruct x0;
simpl.
++
now rewrite H.
++
destruct (
equiv_dec x a0);
simpl.
**
destruct H1 as [?
isdiff].
invcs isdiff.
invcs H4.
elim (
H6 a a0);
simpl;
eauto 2.
now rewrite <-
e.
**
rewrite H.
apply perm_swap.
--
destruct x0;
simpl.
++
eauto with ml.
++
destruct (
equiv_dec x a0);
simpl.
**
rewrite H.
apply perm_swap.
**
rewrite H0 ; [|
eauto with ml].
apply perm_swap.
-
rewrite H0;
trivial.
apply H2.
now rewrite <-
H.
Qed.
Hint Resolve quotient_partitions :
ml.
Definition same_subsets {
A} (
l1 l2:
list (
list A))
:=
exists l1',
Permutation l1 l1' /\
Forall2 (@
Permutation A)
l1'
l2.
Lemma filter_nil_nnil {
A} (
l:
list (
list A)) :
Forall (
fun x =>
not_nil x =
true) (
filter_nil l).
Proof.
induction l; simpl; trivial.
destruct a; simpl; trivial.
constructor; trivial.
Qed.
Lemma nnil_filter_nil_id {
A} (
l:
list (
list A)) :
Forall (
fun x =>
not_nil x =
true)
l ->
filter_nil l =
l.
Proof.
induction l; simpl; trivial.
intros HH; invcs HH.
destruct a; simpl.
- simpl in *; discriminate.
- now rewrite IHl.
Qed.
Lemma add_to_bucket_nnil_perm_preserved {
A}
R {
equiv:
Equivalence R} {
dec:
EqDec A R}
x l l' :
Forall (
fun x =>
not_nil x =
true)
l ->
Permutation l l' ->
is_partition R l ->
Permutation (
add_to_bucket R x l) (
add_to_bucket R x l').
Proof.
Global Instance equiv_class_perm {
A}
R :
Proper (
Permutation (
A:=
A) ==>
iff) (
is_equiv_class R).
Proof.
Global Instance different_buckets_perm {
A}
R :
Proper (
Permutation (
A:=
A) ==>
Permutation (
A:=
A) ==>
iff) (
different_buckets R).
Proof.
Global Instance forall_perm_partition {
A}
R :
Proper (
Forall2 (
Permutation (
A:=
A)) ==>
iff) (
is_partition R).
Proof.
unfold Proper,
respectful.
cut (
forall x y :
list (
list A),
Forall2 (
Permutation (
A:=
A))
x y ->
is_partition R x ->
is_partition R y).
{
intuition;
eauto 2.
eapply H;
try eapply H1.
now symmetry.
}
intros x y f2.
induction f2;
simpl;
trivial.
intros [
HH1 HH2].
invcs HH1.
invcs HH2.
destruct IHf2 as [
HH1'
HH2'].
-
now split.
-
split;
constructor;
trivial.
+
now rewrite <-
H.
+
revert H4.
apply Forall2_Forall_trans.
revert f2.
apply Forall2_incl;
intros.
rewrite <-
H.
now rewrite <-
H4.
Qed.
Global Instance same_subsets_partition {
A} (
R:
list (
list A) -> (
list (
list A) ->
Prop)) {
equiv:
Equivalence R} :
Proper (
same_subsets ==>
iff) (
is_partition R).
Proof.
Lemma forall_perm_add_to_bucket {
A}
R {
equiv:
Equivalence R} {
dec:
EqDec A R}
x l1 l2 :
is_partition R l1 ->
Forall2 (
Permutation (
A:=
A))
l1 l2 ->
Forall2 (
Permutation (
A:=
A)) (
add_to_bucket R x l1) (
add_to_bucket R x l2).
Proof.
intros isp HH1.
induction HH1;
simpl.
-
eauto.
-
specialize (
IHHH1 (
is_partition_cons_inv isp)).
destruct x0;
simpl.
+
destruct y;
trivial.
apply Permutation_nil in H;
discriminate.
+
destruct (
equiv_dec x a);
simpl.
*
destruct y.
--
symmetry in H;
apply Permutation_nil in H;
discriminate.
--
destruct (
equiv_dec x a0).
++
eauto.
++
destruct isp as [
Req Rdiff].
invcs Req.
elim c.
rewrite e.
apply H2.
**
simpl;
eauto.
**
rewrite H;
simpl;
eauto.
*
destruct y.
--
symmetry in H;
apply Permutation_nil in H;
discriminate.
--
destruct (
equiv_dec x a0).
++
destruct isp as [
Req Rdiff].
invcs Req.
elim c.
rewrite e.
apply H2.
**
rewrite H;
simpl;
eauto.
**
simpl;
eauto.
++
eauto.
Qed.
Global Instance same_subsets_equiv {
A} :
Equivalence (@
same_subsets A).
Proof.
constructor;
red;
unfold same_subsets.
-
intros l.
exists l.
split;
reflexivity.
-
intros l1 l2 [
ll [
p p2]].
symmetry in p.
destruct (
Forall2_perm _ _ _ _ p2 p)
as [
xl [
xp xp2]].
exists xl.
split;
trivial.
symmetry;
trivial.
-
intros l1 l2 l3 [
ll [
p p2]] [
ll' [
p'
p2']].
symmetry in p2.
destruct (
Forall2_perm _ _ _ _ p2 p')
as [
xl [
xp xp2]].
exists xl.
split.
+
now rewrite p.
+
etransitivity.
*
symmetry;
eassumption.
*
assumption.
Qed.
Lemma add_to_bucket_diff_perm_swap {
A}
R {
equiv:
Equivalence R} {
dec:
EqDec A R}
x y l :
is_partition R l ->
~
R x y ->
Permutation (
add_to_bucket R y (
add_to_bucket R x l)) (
add_to_bucket R x (
add_to_bucket R y l)).
Proof.
induction l;
simpl;
intros.
-
match_destr.
+
elim H0.
now symmetry.
+
match_destr.
*
now elim H0.
*
apply perm_swap.
-
specialize (
IHl (
is_partition_cons_inv H)
H0).
destruct a;
trivial.
+
destruct (
x ==
a).
*
destruct (
y ==
a).
--
elim H0.
now rewrite e.
--
simpl.
destruct (
y ==
x).
++
elim c;
now rewrite e0.
++
destruct (
x ==
a); [|
congruence].
trivial.
*
destruct (
y ==
a);
simpl.
--
destruct (
y ==
a); [ |
congruence].
destruct (
x ==
y);
trivial.
now elim H0.
--
destruct (
y ==
a); [
congruence | ].
destruct (
x ==
a); [
congruence | ].
now rewrite IHl.
Qed.
Lemma add_to_bucket_same_perm2_swap {
A}
R {
equiv:
Equivalence R} {
dec:
EqDec A R}
x y l :
is_partition R l ->
R x y ->
Forall2 (@
Permutation A) (
add_to_bucket R y (
add_to_bucket R x l)) (
add_to_bucket R x (
add_to_bucket R y l)).
Proof.
induction l;
simpl;
intros.
-
destruct (
y ==
x).
+
destruct (
x ==
y).
*
constructor;
trivial.
apply perm_swap.
*
elim c;
now symmetry.
+
elim c;
now symmetry.
-
specialize (
IHl (
is_partition_cons_inv H)
H0).
destruct a;
simpl;
trivial.
+
destruct (
x ==
a).
*
destruct (
y ==
a).
--
simpl.
destruct (
y ==
x).
++
destruct (
x ==
y).
**
constructor.
---
apply perm_swap.
---
reflexivity.
**
elim c;
now symmetry.
++
elim c;
now symmetry.
--
elim c.
now rewrite <-
e.
*
destruct (
y ==
a);
simpl.
--
destruct (
y ==
a); [ |
congruence].
destruct (
x ==
y);
trivial.
++
elim c.
now rewrite e1.
++
reflexivity.
--
destruct (
y ==
a); [
congruence | ].
destruct (
x ==
a); [
congruence | ].
constructor;
trivial.
Qed.
Global Instance quotient_perm_proper {
A}
R {
equiv:
Equivalence R} {
dec:
EqDec A R} :
Proper (@
Permutation A ==> @
same_subsets A) (
quotient R).
Proof.
Lemma add_to_bucket_new_perm {
A} {
R} {
equiv:
Equivalence R} {
dec:
EqDec A R} (
l :
list (
list A))
a :
Forall (
Forall (
fun y => ~
R a y))
l ->
Permutation ([
a]::
filter_nil l) (
filter_nil (
add_to_bucket R a l)).
Proof.
induction l;
simpl;
intros FF.
-
eauto.
-
invcs FF.
specialize (
IHl H2).
destruct a0;
simpl;
trivial.
invcs H1.
destruct (
a ==
a0).
+
now elim H3.
+
simpl.
rewrite <-
IHl.
apply perm_swap.
Qed.
Global Instance same_subsets_perm_sub {
A} :
subrelation (@
Permutation (
list A))
same_subsets.
Proof.
repeat red; intros.
exists y.
split; trivial.
reflexivity.
Qed.
Global Instance same_subsets_perm2_sub {
A} :
subrelation (
Forall2 (@
Permutation A))
same_subsets.
Proof.
repeat red; intros.
exists x.
eauto.
Qed.
Global Instance not_nil_perm_proper {
A} :
Proper (@
Permutation A ==>
eq) (
not_nil).
Proof.
Lemma add_to_bucket_same_subsets_proper {
A} {
R} {
equiv:
Equivalence R} {
dec:
EqDec A R}
a {
l1 l2} :
is_partition R l1 ->
same_subsets (
filter_nil l1) (
filter_nil l2) ->
same_subsets (
filter_nil (
add_to_bucket R a l1)) (
filter_nil (
add_to_bucket R a l2)).
Proof.
Lemma same_subsets_nnil {
A} {
R} {
equiv:
Equivalence R} {
dec:
EqDec A R} {
l1 l2:
list (
list A)} :
same_subsets l1 l2 ->
Forall (
fun x =>
not_nil x =
true)
l1 ->
Forall (
fun x =>
not_nil x =
true)
l2.
Proof.
Lemma add_to_bucket_nnil_same_subsets_proper {
A} {
R} {
equiv:
Equivalence R} {
dec:
EqDec A R}
a {
l1 l2} :
Forall (
fun x =>
not_nil x =
true)
l1 ->
is_partition R l1 ->
same_subsets l1 l2 ->
same_subsets (
add_to_bucket R a l1) (
add_to_bucket R a l2).
Proof.
Lemma all_equivs_cons_sublist {
A}
R (
x y:
list A)
l :
sublist x y ->
all_equivs R (
y::
l) ->
all_equivs R (
x::
l).
Proof.
Lemma all_equivs_forall_sublist {
A}
R :
Proper (
Forall2 sublist -->
Basics.impl) (@
all_equivs A R).
Proof.
Lemma all_different_cons_sublist {
A}
R (
x y:
list A)
l :
sublist x y ->
all_different R (
y::
l) ->
all_different R (
x::
l).
Proof.
Global Instance different_buckets_sublist {
A R} :
Proper (
sublist -->
sublist -->
Basics.impl) (@
different_buckets A R).
Proof.
Lemma different_buckets_forall_sublist {
A} {
R} (
y:
list A)
l l' :
Forall2 sublist l l' ->
Forall (
different_buckets R y)
l' ->
Forall (
different_buckets R y)
l.
Proof.
intros f2;
induction f2;
simpl;
trivial.
intros f;
invcs f.
constructor;
auto.
eapply different_buckets_sublist;
eauto.
reflexivity.
Qed.
Global Instance all_different_forall_sublist {
A}
R :
Proper (
Forall2 sublist -->
Basics.impl) (@
all_different A R).
Proof.
Lemma is_partition_cons_sublist {
A}
R (
x y:
list A)
l :
sublist y x ->
is_partition R (
x::
l) ->
is_partition R (
y::
l).
Proof.
Global Instance is_partition_forall_sublist {
A}
R :
Proper (
Forall2 sublist -->
Basics.impl) (@
is_partition A R).
Proof.
Lemma all_different_forall_cons_nin {
A}
R a l :
all_different R ([
a] ::
l) ->
Forall (
Forall (
fun y :
A => ~
R a y))
l.
Proof.
Lemma is_partition_forall_cons_nin {
A}
R a l :
is_partition R ([
a] ::
l) ->
Forall (
Forall (
fun y :
A => ~
R a y))
l.
Proof.
Lemma quotient_unquotient {
A} {
R} {
equiv:
Equivalence R} {
dec:
EqDec A R} {
l} :
is_partition R l ->
same_subsets (
filter_nil l) (
quotient R (
concat l)).
Proof.
Lemma Permutation_concat_is_same_subsets {
A}
R {
equiv:
Equivalence R} {
dec:
EqDec A R}
l1 l2 :
is_partition R l1 ->
is_partition R l2 ->
Permutation (
concat l1) (
concat l2) ->
same_subsets (
filter_nil l1) (
filter_nil l2).
Proof.
Lemma Permutation_concat_nnil_is_same_subsets {
A}
R {
equiv:
Equivalence R} {
dec:
EqDec A R}
l1 l2 :
Forall (
fun x =>
not_nil x =
true)
l1 ->
Forall (
fun x =>
not_nil x =
true)
l2 ->
is_partition R l1 ->
is_partition R l2 ->
Permutation (
concat l1) (
concat l2) ->
same_subsets l1 l2.
Proof.
Global Instance is_equiv_class_f2R {
A R} {
equiv:
Equivalence R} :
Proper (
Forall2 R ==>
iff) (@
is_equiv_class A R).
Proof.
Global Instance all_equivs_ff2R {
A R} {
equiv:
Equivalence R} :
Proper (
Forall2 (
Forall2 R) ==>
iff) (@
all_equivs A R).
Proof.
Global Instance different_buckets_f2R {
A R} {
equiv:
Equivalence R} :
Proper (
Forall2 R ==>
Forall2 R ==>
iff) (@
different_buckets A R).
Proof.
Global Instance all_different_ff2R {
A R} {
equiv:
Equivalence R} :
Proper (
Forall2 (
Forall2 R) ==>
iff) (@
all_different A R).
Proof.
Global Instance is_partition_ff2R {
A R} {
equiv:
Equivalence R} :
Proper (
Forall2 (
Forall2 R) ==>
iff) (@
is_partition A R).
Proof.
Lemma add_to_bucket_filter_true {
A} {
R} {
equiv:
Equivalence R} {
dec:
EqDec A R} (
l :
list(
list A)) (
p :
A ->
bool) (
a :
A):
p a =
true ->
is_partition R l ->
Permutation (
filter_nil (
add_to_bucket R a (
map (
filter p)
l))) (
filter_nil (
map (
filter p) (
add_to_bucket R a l))).
Proof.
intros pa isp.
induction l;
simpl.
-
rewrite pa;
eauto.
-
specialize (
IHl (
is_partition_cons_inv isp)).
destruct a0;
simpl;
trivial.
case_eq (
p a0);
intros pa0.
+
destruct (
a ==
a0);
simpl.
*
now rewrite pa,
pa0.
*
rewrite pa0;
simpl;
eauto.
+
induction a1;
simpl.
*
destruct (
a ==
a0);
simpl.
--
rewrite pa,
pa0.
rewrite IHl.
simpl.
symmetry.
rewrite add_to_bucket_new_perm;
trivial.
apply is_partition_forall_cons_nin.
apply (
is_partition_forall_sublist R ([
a]::
l)
_).
++
constructor.
**
reflexivity.
**
apply Forall2_flip.
apply Forall2_map_Forall.
rewrite Forall_forall;
intros.
apply filter_sublist.
++
eapply is_partition_ff2R;
try eapply isp.
constructor.
**
constructor;
trivial.
**
reflexivity.
--
rewrite pa0;
simpl;
trivial.
*
cut_to IHa1.
--
invcs isp.
invcs H.
case_eq (
p a1);
simpl;
intros.
++
destruct (
a ==
a1);
simpl.
**
destruct (
a ==
a0);
simpl.
---
rewrite pa,
pa0,
H;
simpl;
trivial.
---
elim c;
rewrite e.
apply H3;
simpl;
eauto.
**
destruct (
a ==
a0);
simpl.
---
elim c;
rewrite e.
apply H3;
simpl;
eauto.
---
rewrite pa0,
H;
simpl.
now rewrite IHl.
++
rewrite IHa1.
destruct (
a ==
a0).
**
simpl.
now rewrite pa,
pa0,
H;
simpl.
**
simpl.
now rewrite pa0,
H;
simpl.
--
eapply is_partition_forall_sublist;
try eapply isp.
constructor.
++
apply sublist_cons.
apply sublist_skip.
reflexivity.
++
reflexivity.
Qed.
Lemma add_to_bucket_filter_false {
A}
R {
equiv:
Equivalence R} {
dec:
EqDec A R} (
l :
list(
list A)) (
p :
A ->
bool) (
a :
A):
p a =
false ->
filter_nil (
map (
filter p)
l) =
filter_nil (
map (
filter p) (
add_to_bucket R a l)).
Proof.
intros pa.
induction l;
simpl.
-
rewrite pa;
simpl;
trivial.
-
destruct a0;
simpl;
trivial.
case_eq (
p a0);
intros pa0;
simpl.
+
destruct (
equiv_dec a a0);
simpl.
*
rewrite pa.
rewrite pa0;
simpl;
trivial.
*
rewrite pa0;
simpl.
now rewrite IHl.
+
destruct (
equiv_dec a a0);
simpl.
*
rewrite pa.
rewrite pa0;
simpl;
trivial.
*
rewrite pa0;
simpl.
now rewrite IHl.
Qed.
Global Instance perm2_concat_perm {
A} :
Proper (
Forall2 (
Permutation (
A:=
A)) ==> @
Permutation A) (@
concat A).
Proof.
unfold Proper,
respectful.
intros l1 l2 F2.
induction F2;
simpl;
trivial.
rewrite H,
IHF2.
trivial.
Qed.
Global Instance same_subsets_concat_perm {
A} :
Proper (
same_subsets ==> @
Permutation A) (@
concat A).
Proof.
Lemma singleton_is_partition {
A} {
R} {
equiv:
Equivalence R} {
dec:
EqDec A R} {
x :
list A} :
is_equiv_class R x ->
is_partition R [
x].
Proof.
split.
--
red ;
rewrite Forall_forall ;
intros.
simpl in H0.
intuition.
now subst.
--
red.
repeat constructor.
Qed.
Local Existing Instance Equivalence_pullback.
Local Existing Instance EqDec_pullback.
Lemma add_to_bucket_map {
A B:
Type} (
R:
A->
A->
Prop) {
eqR:
Equivalence R} {
decR:
EqDec A R} (
l:
list (
list B))
(
f:
B->
A)
b :
add_to_bucket R (
f b) (
map (
map f)
l) =
map (
map f) (
add_to_bucket (
fun x y :
B =>
R (
f x) (
f y))
b l).
Proof.
induction l;
simpl;
trivial.
rewrite IHl.
destruct a;
simpl;
trivial.
unfold equiv_dec,
EqDec_pullback.
match_destr.
Qed.
Lemma quotient_map {
A B:
Type} (
R:
A->
A->
Prop) {
eqR:
Equivalence R} {
decR:
EqDec A R} (
l:
list B)
(
f:
B->
A) :
quotient R (
map f l) =
map (
map f) (
quotient (
fun x y :
B =>
R (
f x) (
f y))
l).
Proof.
Lemma add_to_bucket_eq_nin {
A} (
decA:
EqDec A eq)
a l :
Forall (
fun x :
list A =>
not_nil x =
true)
l ->
(
forall l' :
list A,
In l'
l -> ~
In a l') ->
(
add_to_bucket eq a l) =
l++[[
a]].
Proof.
intros.
induction l; simpl; trivial.
invcs H.
match_destr.
match_destr.
- red in e; subst.
simpl in H0.
eelim H0; eauto.
simpl; eauto.
- simpl in *.
rewrite IHl; eauto.
Qed.
Lemma nodup_hd_quotient {
A} (
decA:
EqDec A eq)
def (
l:
list A) :
Permutation ((
map (
hd def) (
quotient eq l)))
(
nodup decA l).
Proof.
Lemma add_to_bucket_ext {
A:
Type} (
R1 R2:
A->
A->
Prop) {
eqR1:
Equivalence R1} {
decR1:
EqDec A R1} {
eqR2:
Equivalence R2} {
decR2:
EqDec A R2}
a (
l:
list (
list A)) :
(
forall l'
y,
In y l' ->
In l'
l ->
R1 a y <->
R2 a y) ->
add_to_bucket R1 a l =
add_to_bucket R2 a l.
Proof.
intros.
induction l;
simpl;
trivial.
cut_to IHl; [|
firstorder].
rewrite IHl.
specialize (
H a0);
simpl in H.
match_destr;
simpl in *.
repeat match_destr;
unfold equiv,
complement in *;
firstorder.
Qed.
Lemma quotient_ext {
A:
Type} (
R1 R2:
A->
A->
Prop) {
eqR1:
Equivalence R1} {
decR1:
EqDec A R1} {
eqR2:
Equivalence R2} {
decR2:
EqDec A R2} (
l:
list A) :
ForallPairs (
fun x y =>
R1 x y <->
R2 x y)
l ->
quotient R1 l =
quotient R2 l.
Proof.
Lemma all_different_same_eq {
A}
R {
eqR:
Equivalence R} (
l:
list (
list A))
l1 l2 a b:
all_different R l ->
In l1 l ->
In l2 l ->
In a l1 ->
In b l2 ->
R a b ->
l1 =
l2.
Proof.
induction l;
simpl;
intros.
-
tauto.
-
unfold all_different in H.
invcs H.
rewrite Forall_forall in H7.
unfold different_buckets in H7.
destruct H0;
destruct H1;
subst.
+
trivial.
+
specialize (
H7 _ H0 _ _ H2 H3).
congruence.
+
specialize (
H7 _ H _ _ H3 H2).
symmetry in H4.
congruence.
+
apply IHl;
eauto.
Qed.
End more_quotient.