This module defines possible interleavings of lists.
Require Import List.
Require Import ListSet.
Require Import Bool.
Require Import Permutation.
Require Import Morphisms.
Require Import Setoid.
Require Import EquivDec.
Require Import Equivalence.
Require Import RelationClasses.
Require Import Lia.
Require Import LibUtilsCoqLibAdd.
Require Import LibUtilsLift.
Require Import LibUtilsListAdd.
Require Import LibUtilsAssoc.
Require Import LibUtilsSublist.
Require Import LibUtilsBag.
Section interleaving.
Inductive is_interleaved {
A} :
list (
list A) ->
list A ->
Prop
:=
is_interleaved_concat (
ls1 ls2:
list (
list A)) :
Permutation ls1 ls2 ->
is_interleaved ls2 (
concat ls1)
|
is_interleaved_cons lh ls1 ls2 l x :
is_interleaved (
lh::
ls1)
l ->
Permutation ((
x::
lh)::
ls1)
ls2 ->
is_interleaved ls2 (
x::
l).
Lemma is_interleaved_concat_simple {
A:
Type} (
l:
list (
list A)) :
is_interleaved l (
concat l).
Proof.
Lemma is_interleaved_cons_simple {
A:
Type} (
x:
A)
lh ls l :
is_interleaved (
lh::
ls)
l ->
is_interleaved ((
x::
lh)::
ls) (
x::
l).
Proof.
Global Instance is_interleaved_perm_proper {
A} :
Proper ((@
Permutation (
list A)) ==>
eq ==>
iff) (@
is_interleaved A).
Proof.
cut (
Proper ((@
Permutation (
list A)) ==>
eq ==>
Basics.impl) (@
is_interleaved A));
unfold Proper,
respectful; [
intros H | ];
intros l1 l2 perm ?
l ?;
subst.
{
split;
intros isl.
-
eapply H;
eauto.
-
symmetry in perm.
eapply H;
eauto.
}
intros isl.
revert l2 perm.
induction isl;
simpl;
intros l2 perm.
-
rewrite perm in H.
constructor;
trivial.
-
assert (
inn:
In (
x::
lh)
ls2).
{
rewrite <-
H;
simpl;
eauto. }
destruct (
in_split _ _ inn)
as [
ls11 [
ls12 ?]];
subst.
clear inn.
apply Permutation_cons_app_inv in H.
specialize (
IHisl (
lh::
ls11++
ls12)).
econstructor.
+
apply IHisl.
rewrite H;
trivial.
+
rewrite <-
perm.
apply Permutation_cons_app;
trivial.
Qed.
Lemma is_interleaved_refl {
A} (
l:
list A) :
is_interleaved (
l::
nil)
l.
Proof.
Lemma is_interleaved_nil_l {
A:
Type} (
l:
list A) :
is_interleaved nil l <->
l =
nil.
Proof.
Lemma is_interleaved_perm_concat {
A} {
ls} {
l:
list A}:
is_interleaved ls l ->
Permutation l (
concat ls).
Proof.
induction 1;
simpl.
-
apply Permutation_concat;
trivial.
-
rewrite IHis_interleaved.
rewrite <-
H0.
simpl;
reflexivity.
Qed.
Lemma is_interleaved_both_perm {
A:
Type} {
ls} {
l1 l2:
list A} :
is_interleaved ls l1 ->
is_interleaved ls l2 ->
Permutation l1 l2.
Proof.
Lemma is_interleaved_In {
A:
Type} (
ls:
list (
list A))
l x :
is_interleaved ls l ->
In x l <->
exists l',
In l'
ls /\
In x l'.
Proof.
Lemma is_interleaved_sublist {
A:
Type} {
ls} {
l:
list A} :
is_interleaved ls l ->
Forall (
fun x =>
sublist x l)
ls.
Proof.
induction 1.
-
rewrite <-
H.
apply concat_sublist.
-
invcs IHis_interleaved.
rewrite <-
H0.
constructor.
+
constructor;
trivial.
+
revert H4.
apply Forall_impl;
intros ?
subl.
constructor;
trivial.
Qed.
Lemma is_interleaved_cons_nil_f {
A} {
ls:
list (
list A)} {
l:
list A} :
is_interleaved ls l ->
is_interleaved (
nil ::
ls)
l.
Proof.
Lemma is_interleaved_cons_list {
A}
a ls2 (
l2:
list A) :
is_interleaved ls2 l2 ->
is_interleaved (
a::
ls2) (
a++
l2).
Proof.
Lemma is_interleaved_app {
A}
ls1 l1 ls2 (
l2:
list A) :
is_interleaved ls1 l1 ->
is_interleaved ls2 l2 ->
is_interleaved (
ls1++
ls2) (
l1++
l2).
Proof.
Lemma is_interleaved_map {
A B:
Type} (
f:
A->
B)
ls (
l:
list A) :
is_interleaved ls l ->
is_interleaved (
map (
map f)
ls) (
map f l).
Proof.
Lemma is_interleaved_filter {
A:
Type}
f ls (
l:
list A) :
is_interleaved ls l ->
is_interleaved (
map (
filter f)
ls) (
filter f l).
Proof.
Lemma is_interleaved_filter_nil_f {
A:
Type} {
ls} {
l:
list A} :
is_interleaved ls l ->
is_interleaved (
filter_nil ls)
l.
Proof.
Lemma is_interleaved_filter_nil {
A:
Type}
ls (
l:
list A) :
is_interleaved ls l <->
is_interleaved (
filter_nil ls)
l.
Proof.
Lemma is_interleaved_cons_nil {
A}
ls (
l:
list A) :
is_interleaved ls l <->
is_interleaved (
nil ::
ls)
l.
Proof.
Lemma is_interleaved_app_cons_nil {
A}
ls1 ls2 (
l:
list A) :
is_interleaved (
ls1 ++
nil ::
ls2)
l <->
is_interleaved (
ls1++
ls2)
l.
Proof.
Lemma is_interleaved_nil_r {
A:
Type} (
ls:
list (
list A)) :
is_interleaved ls nil <->
Forall (
eq nil)
ls.
Proof.
Lemma is_interleaved_lookup_none {
A B} {
dec:
EqDec A eq} {
ls:
list (
list (
A*
B))}
l x :
is_interleaved ls l ->
lookup dec l x =
None <->
Forall (
fun ll =>
lookup dec ll x =
None)
ls.
Proof.
Lemma is_interleaved_lookup_some {
A B} {
dec:
EqDec A eq} {
ls:
list (
list (
A*
B))}
l x v :
is_interleaved ls l ->
lookup dec l x =
Some v ->
exists ll,
In ll ls /\
lookup dec ll x =
Some v.
Proof.
intros isl;
induction isl;
intros lo.
-
destruct (
concat_lookup_some_break lo)
as [
ll1 [
ll2 [
ll3 [
eqq [
inn nin]]]]].
subst.
exists ll2;
split;
trivial.
rewrite <-
H.
rewrite in_app_iff;
simpl;
eauto.
-
simpl in lo.
destruct x0.
destruct (
dec x a);
unfold equiv in *.
+
invcs lo.
exists ((
a,
v)::
lh);
simpl.
split.
*
rewrite <-
H;
simpl;
eauto.
*
match_destr;
congruence.
+
destruct (
IHisl lo)
as [
ll [
inn1 inn2]].
simpl in inn1.
destruct inn1.
*
subst.
exists ((
a,
b)::
ll);
simpl.
{
split.
-
rewrite <-
H;
simpl;
eauto.
-
rewrite inn2.
destruct (
dec x a);
congruence.
}
*
exists ll;
split;
trivial.
rewrite <-
H;
simpl;
eauto.
Qed.
Lemma is_interleaved_disjoint_lookup_equiv {
A B} {
dec:
EqDec A eq} {
ls:
list (
list (
A*
B))} :
all_disjoint (
map domain ls) ->
forall l1 l2,
is_interleaved ls l1 ->
is_interleaved ls l2 ->
lookup_equiv l1 l2.
Proof.
Lemma is_interleaved_disjoint_update_first {
A B}
dec ls (
l:
list (
A*
B))
v d:
all_disjoint (
map domain ls) ->
is_interleaved ls l ->
is_interleaved (
map (
fun l0 :
list (
A *
B) =>
update_first dec l0 v d)
ls)
(
update_first dec l v d).
Proof.
Lemma is_interleaved_singleton_inv {
A B} (
l1 l2:
list (
A*
B)) :
is_interleaved (
l1::
nil)
l2 ->
l1 =
l2.
Proof.
Lemma is_interleaved_cons_inv {
A B} {
dec:
EqDec A eq} (
a:(
A*
B))
l1 l2 l3 :
all_disjoint (
map domain ((
a::
l1)::
l2)) ->
is_interleaved ((
a::
l1)::
l2) (
a::
l3) ->
is_interleaved (
l1::
l2)
l3.
Proof.
Lemma is_interleaved_in_dom_cons_inv {
A B} {
dec:
EqDec A eq} {
a:(
A*
B)} {
l1 l2 l3} :
is_interleaved (
l1::
l2) (
a::
l3) ->
all_disjoint (
map domain (
l1::
l2)) ->
In (
fst a) (
domain l1) ->
exists l1',
l1 =
a::
l1'.
Proof.
intros isl disj inn.
destruct a;
simpl in *.
invcs isl.
-
assert (
perm:
Permutation (
filter_nil ls1) (
filter_nil (
l1::
l2))).
{
apply Permutation_filter;
trivial. }
rewrite <-
concat_filter_nil in H.
assert (
nnil:
not_nil l1 =
true).
{
destruct l1;
simpl in *;
tauto. }
simpl in perm;
rewrite nnil in perm.
case_eq (
filter_nil ls1); [
intros eqq |
intros ??
eqq]
;
rewrite eqq in *;
simpl in *;
try discriminate.
destruct l;
simpl in *.
+
cut False; [
contradiction | ].
revert eqq;
clear.
induction ls1;
simpl;
try discriminate.
destruct a;
simpl;
trivial;
try discriminate.
+
invcs H.
destruct (
Permutation_in_nin_inv perm (
a,
b))
as [
eqq2 perm2].
*
simpl;
eauto.
*
rewrite concat_In.
intros [
x [
inn1 inn2]].
invcs disj.
rewrite Forall_forall in H2.
specialize (
H2 (
domain x)).
{
cut_to H2.
-
apply (
H2 a);
trivial;
eapply in_dom;
eauto.
-
apply in_map;
trivial.
unfold filter_nil in inn1.
apply filter_In in inn1;
tauto.
}
*
subst;
eauto.
-
destruct (
Permutation_in_nin_inv H3 (
a,
b))
as [
eqq perm].
+
simpl;
eauto.
+
rewrite concat_In.
intros [
x [
inn1 inn2]].
invcs disj.
rewrite Forall_forall in H1.
specialize (
H1 (
domain x)).
cut_to H1.
*
apply (
H1 a);
trivial;
eapply in_dom;
eauto.
*
apply in_map;
trivial.
+
subst;
eauto.
Qed.
Lemma is_interleaved_in_cons_inv {
A B} {
dec:
EqDec A eq} {
a:(
A*
B)} {
l1 l2 l3} :
is_interleaved (
l1::
l2) (
a::
l3) ->
all_disjoint (
map domain (
l1::
l2)) ->
In a l1 ->
exists l1',
l1 =
a::
l1'.
Proof.
Lemma is_interleaved_cons_dom_eq {
A B} {
dec:
EqDec A eq} {
a:
A} {
b b':
B} {
l1 l2 l3} :
is_interleaved (((
a,
b)::
l1)::
l2) ((
a,
b')::
l3) ->
all_disjoint (
map domain (((
a,
b)::
l1)::
l2)) ->
b =
b'.
Proof.
Lemma is_interleaved_cons_dom_inv {
A B} {
dec:
EqDec A eq} {
a:
A} {
b b':
B} {
l1 l2 l3} :
is_interleaved (((
a,
b)::
l1)::
l2) ((
a,
b')::
l3) ->
all_disjoint (
map domain (((
a,
b)::
l1)::
l2)) ->
is_interleaved (
l1::
l2)
l3.
Proof.
End interleaving.
Section close_enough.
Definition close_enough_lists {
A B:
Type} (
l1 l2:
list (
A*
B)) :=
exists (
ls:
list (
list (
A*
B))),
all_disjoint (
map domain ls) /\
is_interleaved ls l1 /\
is_interleaved ls l2.
Global Instance close_enough_lists_refl {
A B} :
Reflexive (@
close_enough_lists A B).
Proof.
Global Instance close_enough_lists_symm {
A B} :
Symmetric (@
close_enough_lists A B).
Proof.
intros x y [l [disj [isl1 isl2]]].
exists l; eauto.
Qed.
Global Instance close_enough_lists_lookup_equiv {
A B} {
dec:
EqDec A eq} :
subrelation (@
close_enough_lists A B)
lookup_equiv.
Proof.
Lemma close_enough_update_first {
A B}
dec (
l1 l2:
list (
A*
B))
v d :
close_enough_lists l1 l2 ->
close_enough_lists (
update_first dec l1 v d) (
update_first dec l2 v d).
Proof.
Hint Resolve disjoint_nil_l disjoint_nil_r :
fml.
Lemma close_enough_lists_cons {
A B} {
dec:
EqDec A eq} (
a:(
A*
B))
l1 l2 :
close_enough_lists l1 l2 ->
close_enough_lists (
a::
l1) (
a::
l2).
Proof.
destruct a.
intros [
l [
disj [
isl1 isl2]]].
destruct (
in_in_split_domain_or dec l a)
as [[
m1 [
ma [
m2 [
eqq [
inn nin]]]]]|
nin].
-
subst.
exists (
m1++((
a,
b)::
ma)::
m2).
assert (
perm1:
Permutation (
m1 ++ ((
a,
b) ::
ma) ::
m2) (((
a,
b) ::
ma)::
m1 ++
m2)).
{
rewrite <-
Permutation_cons_app;
try reflexivity. }
assert (
perm2:
Permutation (
m1 ++
ma ::
m2) (
ma::
m1 ++
m2)).
{
rewrite <-
Permutation_cons_app;
try reflexivity. }
repeat rewrite perm1.
repeat rewrite perm2 in *.
repeat split.
+
repeat rewrite map_app in *;
simpl in *.
invcs disj.
constructor;
trivial.
revert H1;
apply Forall_impl;
intros.
intros ?;
simpl;
intros inn1 inn2.
eapply H;
try eapply inn2.
destruct inn1;
subst;
trivial.
+
econstructor;
eauto.
+
econstructor;
eauto.
-
exists (((
a,
b)::
nil)::
l);
simpl.
repeat split.
+
constructor;
trivial.
rewrite Forall_map.
revert nin;
apply Forall_impl;
intros.
apply disjoint_cons1;
trivial with fml.
+
econstructor;
eauto.
apply is_interleaved_cons_nil in isl1;
trivial.
+
econstructor;
eauto.
apply is_interleaved_cons_nil in isl2;
trivial.
Qed.
Lemma close_enough_lists_cons_invs {
A B} {
dec:
EqDec A eq} (
a:
A) (
b b':
B)
l1 l2 :
close_enough_lists ((
a,
b)::
l1) ((
a,
b')::
l2) ->
b =
b' /\
close_enough_lists l1 l2.
Proof.
Lemma close_enough_lists_cons_inv {
A B} {
dec:
EqDec A eq} (
a:(
A*
B))
l1 l2 :
close_enough_lists (
a::
l1) (
a::
l2) ->
close_enough_lists l1 l2.
Proof.
End close_enough.