Require Import Coqlib.
Require Import Maps.
Lemma PTree_xfold_none :
forall (
A B:
Type) (
f:
A->
positive->
B->
A) (
m:
PTree.t B) (
x:
A)
p',
(
forall p,
PTree.get p m =
None) ->
PTree.xfold f p'
m x =
x.
Proof.
induction m;
intros;
auto.
simpl.
rewrite IHm1;
try rewrite IHm2;
auto.
destruct o;
auto.
-
generalize (
H 1%
positive).
Transparent PTree.get.
simpl.
congruence.
-
intros;
generalize (
H (
xI p));
simpl;
auto.
-
intros;
generalize (
H (
xO p));
simpl;
auto.
Qed.
Lemma PTree_xfold_same :
forall (
A B:
Type) (
f:
A->
positive->
B->
A) (
m1 m2:
PTree.t B) (
x y:
A)
p',
(
forall p,
m1!
p =
m2!
p) ->
x =
y ->
PTree.xfold f p'
m1 x =
PTree.xfold f p'
m2 y.
Proof.
induction m1;
simpl;
intros;
auto.
rewrite PTree_xfold_none;
auto.
intros p;
rewrite <-
H;
auto.
induction p;
simpl;
auto.
subst;
destruct m2.
generalize (
H xH);
simpl;
intros;
subst.
repeat rewrite PTree_xfold_none;
auto.
intros p;
generalize (
H (
xO p));
simpl;
auto.
intros p;
generalize (
H (
xI p));
simpl;
auto.
generalize (
H xH);
simpl;
intros;
subst.
destruct o0.
apply IHm1_2.
intros p;
generalize (
H (
xI p));
simpl;
auto.
f_equal.
apply IHm1_1;
auto.
intros p;
generalize (
H (
xO p));
simpl;
auto.
apply IHm1_2.
intros p;
generalize (
H (
xI p));
simpl;
auto.
apply IHm1_1;
auto.
intros p;
generalize (
H (
xO p));
simpl;
auto.
Qed.
Set Implicit Arguments.
Module P2Tree :
TREE with Definition elt := (
positive *
positive)%
type.
Definition elt:
Type := (
positive *
positive)%
type.
Definition elt_eq:
forall (
a b:
elt), {
a =
b} + {
a <>
b}.
Proof.
decide equality.
apply peq.
apply peq.
Defined.
Definition t (
A:
Type) :
Type :=
PTree.t (
PTree.t A).
Definition empty (
A:
Type) :
t A :=
PTree.empty _.
Definition get (
A:
Type) (
a:
elt) (
m:
t A) :
option A :=
let (
a1,
a2) :=
a in
match PTree.get a1 m with
|
None =>
None
|
Some m =>
PTree.get a2 m
end.
Definition set (
A:
Type) (
a:
elt) (
v:
A) (
m:
t A) :
t A :=
let (
a1,
a2) :=
a in
let m1 :=
match PTree.get a1 m with
|
None =>
PTree.set a2 v (
PTree.empty _)
|
Some m1 =>
PTree.set a2 v m1
end in
PTree.set a1 m1 m.
Definition remove (
A:
Type) (
a:
elt) (
m:
t A) :
t A :=
let (
a1,
a2) :=
a in
let m1 :=
match PTree.get a1 m with
|
None =>
PTree.empty _
|
Some m1 =>
m1
end in
PTree.set a1 (
PTree.remove a2 m1)
m.
The ``good variables'' properties for trees, expressing
commutations between get, set and remove.
Lemma gempty:
forall (
A:
Type) (
i:
elt),
get i (
empty A) =
None.
Proof.
Lemma gss:
forall (
A:
Type) (
i:
elt) (
x:
A) (
m:
t A),
get i (
set i x m) =
Some x.
Proof.
Lemma gso:
forall (
A:
Type) (
i j:
elt) (
x:
A) (
m:
t A),
i <>
j ->
get i (
set j x m) =
get i m.
Proof.
Lemma gsspec:
forall (
A:
Type) (
i j:
elt) (
x:
A) (
m:
t A),
get i (
set j x m) =
if elt_eq i j then Some x else get i m.
Proof.
intros A i j x m.
destruct (
elt_eq i j);
subst.
apply gss.
apply gso;
auto.
Qed.
Lemma gsident:
forall (
A:
Type) (
i:
elt) (
m:
t A) (
v:
A),
get i m =
Some v ->
set i v m =
m.
Proof.
Lemma grs:
forall (
A:
Type) (
i:
elt) (
m:
t A),
get i (
remove i m) =
None.
Proof.
Lemma gro:
forall (
A:
Type) (
i j:
elt) (
m:
t A),
i <>
j ->
get i (
remove j m) =
get i m.
Proof.
Lemma grspec:
forall (
A:
Type) (
i j:
elt) (
m:
t A),
get i (
remove j m) =
if elt_eq i j then None else get i m.
Proof.
intros A i j m.
destruct (
elt_eq i j);
subst.
apply grs.
apply gro;
auto.
Qed.
Extensional equality between trees.
Definition beq (
A:
Type) (
f:
A ->
A ->
bool) (
m1 m2:
t A) :
bool :=
let mb :=
PTree.combineT1
(
fun m'1
m'2 =>
match m'1,
m'2
with
|
Some m'1,
Some m'2 =>
Some (
PTree.beq f m'1
m'2)
|
Some m'1,
None =>
Some (
PTree.beq f m'1 (
PTree.empty _))
|
None,
Some m'2 =>
Some (
PTree.beq f (
PTree.empty _)
m'2)
|
None,
None =>
None
end)
m1 m2
in PTree.fold (
fun x _ y =>
y &&
x)
mb true.
Lemma beq_correct:
forall (
A:
Type) (
eqA:
A ->
A ->
bool) (
t1 t2:
t A),
beq eqA t1 t2 =
true <->
(
forall (
x:
elt),
match get x t1,
get x t2 with
|
None,
None =>
True
|
Some y1,
Some y2 =>
eqA y1 y2 =
true
|
_,
_ =>
False
end).
Proof.
Applying a function to all data of a tree.
Definition map (
A B:
Type) (
f:
elt ->
A ->
B) (
m:
t A) :
t B :=
PTree.map (
fun a1 =>
PTree.map (
fun a2 =>
f (
a1,
a2)))
m.
Lemma gmap:
forall (
A B:
Type) (
f:
elt ->
A ->
B) (
i:
elt) (
m:
t A),
get i (
map f m) =
option_map (
f i) (
get i m).
Proof.
Same as map, but the function does not receive the elt argument.
Definition map1 (
A B:
Type) (
f:
A ->
B) (
m:
t A) :
t B :=
PTree.map1 (
PTree.map1 f)
m.
Lemma gmap1:
forall (
A B:
Type) (
f:
A ->
B) (
i:
elt) (
m:
t A),
get i (
map1 f m) =
option_map f (
get i m).
Proof.
Applying a function pairwise to all data of two trees.
Definition combineT1 (
A B C:
Type) (
f:
option A ->
option B ->
option C) (
m1:
t A) (
m2:
t B) :
t C :=
PTree.combineT1 (
fun om1 om2 =>
match om1,
om2 with
|
None,
None =>
None
|
None,
Some m2 =>
Some (
PTree.combineT1 f (@
PTree.empty _)
m2)
|
Some m2,
None =>
Some (
PTree.combineT1 f m2 (@
PTree.empty _))
|
Some m1,
Some m2 =>
Some (
PTree.combineT1 f m1 m2)
end)
m1 m2.
Lemma gcombine:
forall (
A B C:
Type) (
f:
option A ->
option B ->
option C),
f None None =
None ->
forall (
m1:
t A) (
m2:
t B) (
i:
elt),
get i (
combineT1 f m1 m2) =
f (
get i m1) (
get i m2).
Proof.
Lemma combine_commut:
forall (
A B:
Type) (
f g:
option A ->
option A ->
option B),
(
forall (
i j:
option A),
f i j =
g j i) ->
forall (
m1 m2:
t A),
combineT1 f m1 m2 =
combineT1 g m2 m1.
Proof.
Enumerating the bindings of a tree.
Fixpoint xelements (
A :
Type) (
m :
t A) (
i :
positive)
(
k:
list (
positive *
positive *
A)) {
struct m} :
list (
positive *
positive *
A) :=
match m with
|
PTree.Leaf =>
k
|
PTree.Node l None r =>
xelements l (
xO i) (
xelements r (
xI i)
k)
|
PTree.Node l (
Some x)
r =>
let elmts :=
PTree.fold
(
fun l x2 a => ((
PTree.prev i,
x2),
a)::
l)
x (@
nil _)
in
xelements l (
xO i) (
elmts ++
xelements r (
xI i)
k)
end.
Definition elements (
A:
Type) (
m :
t A) :=
xelements m xH nil.
Remark xelements_append:
forall A (
m:
t A)
i k1 k2,
xelements m i (
k1 ++
k2) =
xelements m i k1 ++
k2.
Proof.
induction m;
intros;
simpl.
-
auto.
-
destruct o;
rewrite IHm2.
+
rewrite <-
IHm1;
auto.
rewrite app_assoc.
auto.
+
rewrite <-
IHm1;
auto.
Qed.
Remark xelements_leaf:
forall A i,
xelements (@
PTree.Leaf (
PTree.t A))
i nil =
nil.
Proof.
intros; reflexivity.
Qed.
Remark xelements_node:
forall A (
m1:
t A)
o (
m2:
t A)
i,
xelements (
PTree.Node m1 o m2)
i nil =
xelements m1 (
xO i)
nil
++
match o with None =>
nil |
Some v =>
PTree.fold
(
fun l x2 a => ((
PTree.prev i,
x2),
a)::
l)
v (@
nil _)
end
++
xelements m2 (
xI i)
nil.
Proof.
Lemma xelements_incl:
forall (
A:
Type) (
m:
t A) (
i :
positive)
k x,
In x k ->
In x (
xelements m i k).
Proof.
induction m;
intros;
simpl.
-
auto.
-
destruct o.
+
apply IHm1.
apply in_app.
right.
auto.
+
auto.
Qed.
Lemma gleaf :
forall (
A:
Type) (
i1 i2:
positive), @
get A (
i1,
i2)
PTree.Leaf =
None.
Proof.
Lemma fold_left_acc_in {
A B:
Type}:
forall (
f:
A ->
B) (
l:
list A)
k res,
fold_left (
fun (
res :
list B) (
i :
A) => (
f i)::
res)
l k =
res ->
forall (
i :
B),
In i k ->
In i res.
Proof.
induction l ; intros.
- simpl in H. subst. auto.
- simpl in H. eapply IHl ; eauto.
right; auto.
Qed.
Lemma fold_left_acc {
A B:
Type}:
forall (
f:
A ->
B) (
l:
list A)
k res,
fold_left (
fun (
res :
list B) (
i :
A) => (
f i)::
res)
l k =
res ->
forall (
i :
A),
In i l ->
In (
f i)
res .
Proof.
induction l ;
intros.
-
inv H0.
-
inv H0.
+
simpl.
eapply fold_left_acc_in;
eauto.
left;
auto.
+
simpl.
eapply IHl;
eauto.
Qed.
Lemma in_fold_left_acc {
A B:
Type}:
forall (
f:
A ->
B) (
l:
list A)
k res,
fold_left (
fun (
res :
list B) (
i :
A) => (
f i)::
res)
l k =
res ->
forall (
i :
B),
In i res ->
In i k \/
exists j,
In j l /\
i =
f j.
Proof.
induction l ; intros.
- simpl in H. subst. auto.
- simpl in H.
exploit IHl; eauto. intros [P | P].
+ inv P.
* right. exists a; split; try left ; auto.
* auto.
+ right. inv P. inv H1. exists x ; split; try right; auto.
Qed.
Lemma xelements_correct:
forall (
A:
Type) (
m:
t A) (
i1 i2 j :
positive) (
v:
A)
k,
get (
i1,
i2)
m =
Some v ->
In (
PTree.prev (
PTree.prev_append i1 j),
i2,
v) (
xelements m j k).
Proof.
Lemma elements_correct:
forall (
A:
Type) (
m:
t A) (
i:
elt) (
v:
A),
get i m =
Some v ->
In (
i,
v) (
elements m).
Proof.
Lemma in_xelements:
forall (
A:
Type) (
m:
t A) (
i1 i2 k:
positive) (
v:
A) ,
In (
i1,
i2,
v) (
xelements m k nil) ->
exists j,
i1 =
PTree.prev (
PTree.prev_append j k) /\
get (
j,
i2)
m =
Some v.
Proof.
induction m;
intros.
-
rewrite xelements_leaf in H.
contradiction.
-
rewrite xelements_node in H.
rewrite !
in_app_iff in H.
destruct H as [
P | [
P |
P]].
+
exploit IHm1;
eauto.
intros (
j &
Q &
R).
exists (
xO j);
split;
auto.
+
destruct o;
simpl in P;
intuition auto.
rewrite PTree.fold_spec in P.
set (
f:=
fun (
p:
positive *
A) => (
PTree.prev k,
fst p,
snd p))
in *.
eapply in_fold_left_acc with (
f0:=
f)
in P ;
eauto.
inv P;
inv H.
inv H0.
unfold f in H1.
inv H1.
exists xH;
split;
auto.
simpl.
eapply PTree.elements_complete;
eauto.
destruct x ;
auto.
+
exploit IHm2;
eauto.
intros (
j &
Q &
R).
exists (
xI j);
auto.
Qed.
Theorem elements_complete:
forall (
A:
Type) (
m:
t A) (
i:
elt) (
v:
A),
In (
i,
v) (
elements m) ->
get i m =
Some v.
Proof.
Remark list_norepet_map:
forall (
A B:
Type) (
f:
A ->
B) (
l:
list A),
list_norepet (
List.map f l) ->
list_norepet l.
Proof.
induction l;
simpl;
intros.
constructor.
inv H.
constructor;
auto.
red;
intros;
elim H2.
apply List.in_map;
auto.
Qed.
Definition xkeys (
A:
Type) (
m:
t A) (
i:
positive) :=
List.map (@
fst (
positive *
positive)
A) (
xelements m i nil).
Remark xkeys_leaf:
forall A i,
xkeys (@
PTree.Leaf (
PTree.t A))
i =
nil.
Proof.
intros; reflexivity.
Qed.
Remark xkeys_node:
forall A (
m1:
t A)
o (
m2:
t A)
i,
xkeys (
PTree.Node m1 o m2)
i =
xkeys m1 (
xO i)
++
match o with None =>
nil |
Some v =>
List.map (@
fst (
positive *
positive)
A)
(
PTree.fold
(
fun l x2 a => ((
PTree.prev i,
x2),
a)::
l)
v (@
nil _))
end
++
xkeys m2 (
xI i).
Proof.
Lemma in_xkeys:
forall (
A:
Type) (
m:
t A) (
i k1 k2:
positive),
In (
k1,
k2) (
xkeys m i) ->
(
exists j,
k1 =
PTree.prev (
PTree.prev_append j i)).
Proof.
unfold xkeys;
intros.
apply (
list_in_map_inv)
in H.
destruct H as (((
j1,
j2),
v) &
H0 &
H).
simpl in *.
inv H0.
exploit in_xelements;
eauto.
intros (
k &
P &
Q).
exists k;
auto.
Qed.
Lemma in_fold_left_acc_map {
A B:
Type}:
forall (
f:
A ->
B) (
l:
list A)
k,
fold_left (
fun (
res :
list B) (
i :
A) => (
f i)::
res)
l k = (
rev (
List.map f l)) ++
k.
Proof.
induction l ;
simpl;
intros.
-
auto.
-
simpl.
rewrite IHl;
eauto.
rewrite app_ass.
auto.
Qed.
Lemma rev_no_repet :
forall (
A:
Type) (
l:
list A),
list_norepet l ->
list_norepet (
rev l).
Proof.
induction l ;
intros;
auto.
simpl.
inv H.
apply list_norepet_app;
repeat split;
auto.
-
constructor;
auto.
apply list_norepet_nil.
-
red ;
intros.
inv H0;
auto.
intro Hcont;
subst.
elim H2;
apply in_rev;
auto.
Qed.
Lemma list_disjoint_app :
forall (
A:
Type) (
l1 l2 l3:
list A),
list_disjoint l1 l3 ->
list_disjoint l2 l3 ->
list_disjoint (
l1 ++
l2)
l3.
Proof.
induction l1 ;
intros;
simpl;
auto.
red ;
intros.
intro;
subst.
inv H1.
-
eelim H;
eauto.
left;
auto.
-
apply in_app in H3.
inv H3.
+
eelim H ;
eauto.
right;
auto.
+
eelim H0;
eauto.
Qed.
Lemma list_disjoint_rev :
forall (
A:
Type) (
l1 l2:
list A),
list_disjoint l1 l2 ->
list_disjoint (
rev l1)
l2.
Proof.
induction l1 ;
intros;
auto.
simpl.
red;
intros.
intro Hcont;
subst.
apply in_app in H0.
inv H0.
eelim H;
eauto.
-
right;
auto.
apply in_rev;
auto.
-
inv H2;
auto.
eelim H;
eauto.
left;
auto.
Qed.
Lemma list_norepet_map_fst :
forall A i0 t0 p,
list_norepet
(
List.map (
fun x :
positive *
A => (
PTree.prev i0,
fst x)) (
PTree.xelements t0 p nil)).
Proof.
Lemma disjoint_map_fst :
forall A l (
t1 :
PTree.t A) (
p i :
positive),
(
forall j :
positive, ~
In (
PTree.prev i,
j)
l) ->
list_disjoint
(
List.map (
fun x :
positive *
A => (
PTree.prev i,
fst x)) (
PTree.xelements t1 p nil))
l.
Proof.
Lemma xelements_keys_norepet:
forall (
A:
Type) (
m:
t A) (
i:
positive),
list_norepet (
xkeys m i).
Proof.
induction m;
intros.
-
rewrite xkeys_leaf;
constructor.
-
assert (
NOTIN1:
forall j, ~
In ((
PTree.prev i),
j) (
xkeys m1 (
xO i))).
{
red;
intros.
exploit in_xkeys;
eauto.
intros (
j0 &
EQ).
rewrite PTree.prev_append_prev in EQ.
simpl in EQ.
apply PTree.prev_append_inj in EQ.
discriminate. }
assert (
NOTIN2:
forall j, ~
In ((
PTree.prev i),
j) (
xkeys m2 (
xI i))).
{
red;
intros.
exploit in_xkeys;
eauto.
intros (
j0 &
EQ).
rewrite PTree.prev_append_prev in EQ.
simpl in EQ.
apply PTree.prev_append_inj in EQ.
discriminate. }
assert (
DISJ:
forall x1 x2,
In (
x1,
x2) (
xkeys m1 (
xO i)) ->
In (
x1,
x2) (
xkeys m2 (
xI i)) ->
False).
{
intros.
exploit in_xkeys.
eexact H.
intros (
j1 &
EQ1).
exploit in_xkeys.
eexact H0.
intros (
j2 &
EQ2).
rewrite PTree.prev_append_prev in *.
simpl in *.
rewrite EQ2 in EQ1.
apply PTree.prev_append_inj in EQ1.
discriminate. }
rewrite xkeys_node.
apply list_norepet_append.
+
auto.
+
apply list_norepet_append;
auto.
*
destruct o;
simpl;
try constructor.
rewrite PTree.fold_spec.
rewrite in_fold_left_acc_map.
rewrite <-
map_rev.
rewrite <-
app_nil_end.
rewrite map_map.
rewrite map_rev.
apply rev_no_repet.
simpl.
apply list_norepet_map_fst.
*
destruct o ;
simpl.
{
rewrite PTree.fold_spec.
rewrite in_fold_left_acc_map ;
eauto.
rewrite <-
map_rev.
rewrite <-
app_nil_end.
rewrite map_map.
rewrite map_rev.
apply list_disjoint_rev.
simpl.
apply disjoint_map_fst;
auto.
}
{
red ;
intros;
auto. }
+
destruct o;
simpl;
try constructor.
rewrite PTree.fold_spec.
rewrite in_fold_left_acc_map.
rewrite <-
map_rev.
rewrite <-
app_nil_end.
rewrite map_map.
rewrite map_rev.
apply list_disjoint_sym.
apply list_disjoint_app.
apply list_disjoint_rev.
simpl.
{
apply disjoint_map_fst;
auto. }
{
red;
intros (
x1,
y1) (
x2,
y2)
Hin1 Hin2 Hcont;
inv Hcont;
eauto. }
{
red;
intros (
x1,
y1) (
x2,
y2)
Hin1 Hin2 Hcont;
inv Hcont;
eauto. }
Qed.
Theorem elements_keys_norepet:
forall (
A:
Type) (
m:
t A),
list_norepet (
List.map (@
fst elt A) (
elements m)).
Proof.
Lemma get_node_none :
forall A (
t0:
PTree.t A)
m1 m2,
(
forall i1 i2,
get (
i1,
i2) (
PTree.Node m1 (
Some t0)
m2) =
None) ->
forall i2,
PTree.get i2 t0 =
None.
Proof.
induction t0;
intros;
simpl.
-
apply PTree.gleaf.
-
specialize (
H xH i2).
simpl in H.
auto.
Qed.
Remark xelements_empty:
forall (
A:
Type) (
m:
t A)
i, (
forall i,
get i m =
None) ->
xelements m i nil =
nil.
Proof.
Lemma option_rel_Some_None_elim :
forall (
A B:
Type) (
R:
A ->
B ->
Prop) (
m1 m2:
t A)
t0 n1 n2,
(
forall i :
elt,
option_rel R (
get i (
PTree.Node m1 (
Some t0)
m2)) (
get i (
PTree.Node n1 None n2))) ->
(
forall i,
t0 !
i =
None).
Proof.
intros.
specialize (
H (
xH,
i)).
inv H.
destruct t0;
auto.
Qed.
Lemma option_rel_None_Some_elim :
forall (
A B:
Type) (
R:
A ->
B ->
Prop) (
m1 m2:
t A)
t0 n1 n2,
(
forall i :
elt,
option_rel R (
get i (
PTree.Node m1 None m2)) (
get i (
PTree.Node n1 (
Some t0)
n2))) ->
(
forall i,
t0 !
i =
None).
Proof.
intros.
specialize (
H (
xH,
i)).
inv H.
destruct t0;
auto.
Qed.
Lemma option_rel_Some_Some_elim :
forall (
A B:
Type) (
R:
A ->
B ->
Prop) (
m1 m2:
t A)
t0 t1 n1 n2,
(
forall i :
elt,
option_rel R (
get i (
PTree.Node m1 (
Some t0)
m2)) (
get i (
PTree.Node n1 (
Some t1)
n2))) ->
(
forall i,
option_rel R (
t0 !
i) (
t1 !
i)).
Proof.
intros.
specialize (
H (
xH,
i)).
inv H.
destruct t0;
auto;
constructor.
constructor;
auto.
Qed.
Lemma list_forall2_rev :
forall (
A B:
Type) (
R:
A ->
B ->
Prop)
l1 l2,
list_forall2 R l1 l2 ->
list_forall2 R (
rev l1) (
rev l2).
Proof.
induction 1 ;
intros.
-
simpl;
auto.
constructor.
-
simpl.
apply list_forall2_app;
auto.
repeat constructor;
auto.
Qed.
Lemma list_forall2_map :
forall A B f (
R :
A ->
B ->
Prop)
l1 l2 ,
let RR := (
fun (
i_x :
positive *
positive *
A) (
i_y :
positive *
positive *
B) =>
fst i_x =
fst i_y /\
R (
snd i_x) (
snd i_y))
in
let RR0 := (
fun (
i_x :
positive *
A) (
i_y :
positive *
B) =>
fst i_x =
fst i_y /\
R (
snd i_x) (
snd i_y))
in
(
forall a b,
RR0 a b ->
RR (
f A a) (
f B b)) ->
list_forall2 RR0 l1 l2 ->
list_forall2 RR (
List.map (
f A)
l1) (
List.map (
f B)
l2).
Proof.
intros A B f R.
induction 2 ; intros.
- simpl; auto. constructor.
- simpl. constructor; auto.
Qed.
Theorem elements_canonical_order':
forall (
A B:
Type) (
R:
A ->
B ->
Prop) (
m:
t A) (
n:
t B),
(
forall i,
option_rel R (
get i m) (
get i n)) ->
list_forall2
(
fun i_x i_y =>
fst i_x =
fst i_y /\
R (
snd i_x) (
snd i_y))
(
elements m) (
elements n).
Proof.
Theorem elements_canonical_order:
forall (
A B:
Type) (
R:
A ->
B ->
Prop) (
m:
t A) (
n:
t B),
(
forall i x,
get i m =
Some x ->
exists y,
get i n =
Some y /\
R x y) ->
(
forall i y,
get i n =
Some y ->
exists x,
get i m =
Some x /\
R x y) ->
list_forall2
(
fun i_x i_y =>
fst i_x =
fst i_y /\
R (
snd i_x) (
snd i_y))
(
elements m) (
elements n).
Proof.
intros.
apply elements_canonical_order'.
intros.
destruct (
get i m)
as [
x|]
eqn:
GM.
exploit H;
eauto.
intros (
y &
P &
Q).
rewrite P;
constructor;
auto.
destruct (
get i n)
as [
y|]
eqn:
GN.
exploit H0;
eauto.
intros (
x &
P &
Q).
congruence.
constructor.
Qed.
Theorem elements_extensional:
forall (
A:
Type) (
m n:
t A),
(
forall i,
get i m =
get i n) ->
elements m =
elements n.
Proof.
intros.
exploit (@
elements_canonical_order'
_ _ (
fun (
x y:
A) =>
x =
y)
m n).
intros.
rewrite H.
destruct (
get i n);
constructor;
auto.
induction 1.
auto.
destruct a1 as [
a2 a3];
destruct b1 as [
b2 b3];
simpl in *.
destruct H0.
congruence.
Qed.
Lemma fold_left_acc_k :
forall (
A B :
Type) (
f :
A ->
B) (
l :
list A) (
k :
list B),
fold_left (
fun acc i => (
f i) ::
acc)
l k = (
fold_left (
fun k i =>
f i ::
k)
l nil) ++
k.
Proof.
induction l ;
intros;
auto.
simpl.
rewrite IHl;
auto.
symmetry.
rewrite IHl;
auto.
rewrite app_ass.
simpl.
auto.
Qed.
Lemma xelements_remove:
forall (
A:
Type)
v (
m:
t A)
i1 i2 j,
get (
i1,
i2)
m =
Some v ->
exists l1 l2,
xelements m j nil =
l1 ++ (
PTree.prev (
PTree.prev_append i1 j),
i2,
v) ::
l2
/\
xelements (
remove (
i1,
i2)
m)
j nil =
l1 ++
l2.
Proof.
induction m;
intros.
-
rewrite gleaf in H;
discriminate.
-
Transparent PTree.set.
assert (
REMOVE:
xelements (
remove (
i1,
i2) (
PTree.Node m1 o m2))
j nil =
xelements (
match i1 with
|
xH =>
PTree.Node m1
(
match o with
|
None =>
None
|
Some t =>
Some (
PTree.remove i2 t)
end)
m2
|
xO ii =>
PTree.Node (
remove (
ii,
i2)
m1)
o m2
|
xI ii =>
PTree.Node m1 o (
remove (
ii,
i2)
m2)
end)
j nil).
{
destruct i1;
simpl remove.
-
destruct m1;
auto.
-
auto.
-
destruct o;
auto.
inv H.
}
rewrite REMOVE.
destruct i1;
simpl in H.
+
assert (
GET :
get (
i1,
i2)
m2 =
Some v)
by auto.
destruct (
IHm2 i1 i2 (
xI j)
GET)
as (
l1 &
l2 &
EQ &
EQ').
exists (
xelements m1 (
xO j)
nil ++
match o with None =>
nil |
Some x =>
PTree.fold
(
fun (
l0 :
list (
positive *
positive *
A)) (
x2 :
positive) (
a :
A) => (
PTree.prev j,
x2,
a) ::
l0)
x
nil
end ++
l1).
exists l2;
split.
*
rewrite xelements_node,
EQ, !
app_ass;
auto.
*
rewrite xelements_node,
EQ', !
app_ass.
auto.
+
assert (
GET :
get (
i1,
i2)
m1 =
Some v)
by auto.
destruct (
IHm1 i1 i2 (
xO j)
GET)
as (
l1 &
l2 &
EQ &
EQ').
exists l1;
exists (
l2 ++
match o with
None =>
nil
|
Some x =>
PTree.fold
(
fun (
l0 :
list (
positive *
positive *
A)) (
x2 :
positive) (
a :
A) => (
PTree.prev j,
x2,
a) ::
l0)
x
nil
end ++
xelements m2 (
xI j)
nil);
split.
rewrite xelements_node,
EQ, !
app_ass.
auto.
rewrite xelements_node,
EQ', !
app_ass.
auto.
+
simpl PTree.prev_append.
rewrite !
xelements_node;
auto.
destruct o ;
try congruence.
rewrite !
PTree.fold_spec.
generalize H ;
intros GET.
apply PTree.elements_remove in H.
destruct H as [
l1 [
l2 [
EQ1 EQ2]]].
rewrite EQ1,
EQ2.
rewrite !
fold_left_app.
simpl.
set (
F:= (
fun (
a :
list (
positive *
positive *
A)) (
p :
positive *
A) => (
PTree.prev j,
fst p,
snd p) ::
a))
in *.
simpl.
unfold F at 1.
rewrite fold_left_acc_k.
rewrite app_ass.
fold F.
unfold F at 3.
rewrite fold_left_acc_k.
fold F.
rewrite !
app_ass.
simpl.
exists (
xelements m1 j~0
nil ++
fold_left F l2 nil).
rewrite <-
app_ass.
exists (
fold_left F l1 nil ++
xelements m2 j~1
nil).
split;
auto.
rewrite <-
app_ass.
auto.
Qed.
Theorem elements_remove:
forall (
A:
Type)
i v (
m:
t A),
get i m =
Some v ->
exists l1 l2,
elements m =
l1 ++ (
i,
v) ::
l2 /\
elements (
remove i m) =
l1 ++
l2.
Proof.
Fixpoint xfold (
A B:
Type) (
f:
B ->
elt ->
A ->
B)
(
i:
positive) (
m:
t A) (
v:
B) {
struct m} :
B :=
match m with
|
PTree.Leaf =>
v
|
PTree.Node l None r =>
let v1 :=
xfold f (
xO i)
l v in
xfold f (
xI i)
r v1
|
PTree.Node l (
Some x)
r =>
let v1 :=
xfold f (
xO i)
l v in
let v2 :=
fold_left (
fun k j =>
f k ((
PTree.prev i), (
fst j)) (
snd j)) (
rev (
PTree.elements x))
v1 in
xfold f (
xI i)
r v2
end.
Definition fold (
A B :
Type) (
f:
B ->
elt ->
A ->
B) (
m:
t A) (
v:
B) :=
xfold f xH m v.
Lemma fold_left_PTree_fold_glue :
forall (
A B:
Type) (
f:
B ->
elt ->
A ->
B)
e l k,
fold_left (
fun (
k :
B) (
j0 :
positive *
A) =>
f k (
e,
fst j0) (
snd j0))
(
rev l)
k
=
fold_left (
fun (
a :
B) (
p :
elt *
A) =>
f a (
fst p) (
snd p))
(
rev (
List.map (
fun i :
positive *
A => (
e,
fst i,
snd i))
l))
k.
Proof.
Lemma xfold_spec:
forall (
A B:
Type) (
f:
B ->
elt ->
A ->
B) (
m:
t A) (
v:
B)
j,
xfold f j m v =
List.fold_left (
fun a p =>
f a (
fst p) (
snd p)) (
xelements m j nil)
v.
Proof.
Theorem fold_spec:
forall (
A B:
Type) (
f:
B ->
elt ->
A ->
B) (
v:
B) (
m:
t A),
fold f m v =
List.fold_left (
fun a p =>
f a (
fst p) (
snd p)) (
elements m)
v.
Proof.
Fixpoint fold1 (
A B:
Type) (
f:
B ->
A ->
B) (
m:
t A) (
v:
B) :
B :=
match m with
|
PTree.Leaf =>
v
|
PTree.Node l None r =>
let v1 :=
fold1 f l v in
fold1 f r v1
|
PTree.Node l (
Some x)
r =>
let v1 :=
fold1 f l v in
let v2 :=
fold_left (
fun k j =>
f k (
snd j)) (
rev (
PTree.elements x))
v1 in
fold1 f r v2
end.
Lemma glue2 :
forall (
A B:
Type) (
f:
B ->
A ->
B)
e l k,
(
fold_left (
fun (
k :
B) (
j :
positive *
A) =>
f k (
snd j))
(
rev l)
k) =
fold_left (
fun (
a :
B) (
p :
positive *
positive *
A) =>
f a (
snd p))
(
rev (
List.map (
fun i0 :
positive *
A => (
e,
fst i0,
snd i0))
l))
k.
Proof.
Lemma fold1_xelements:
forall (
A B:
Type) (
f:
B ->
A ->
B)
m i v l,
List.fold_left (
fun a p =>
f a (
snd p))
l (
fold1 f m v) =
List.fold_left (
fun a p =>
f a (
snd p)) (
xelements m i l)
v.
Proof.
Lemma fold1_spec:
forall (
A B:
Type) (
f:
B ->
A ->
B) (
v:
B) (
m:
t A),
fold1 f m v =
List.fold_left (
fun a p =>
f a (
snd p)) (
elements m)
v.
Proof.
End P2Tree.