An extension of FSetAVL (finite sets as balanced binary search trees)
with extra interval-based operations, more efficient than standard
operations.
Require Import FSetInterface.
Require FSetAVL.
Require Import Coqlib.
Module Make(
X:
OrderedType).
Include FSetAVL.Make(
X).
Module Raw :=
MSet.Raw.
Section MEM_BETWEEN.
mem_between above below s is true iff there exists an element of s
that belongs to the interval described by the predicates above and below.
Using the monotonicity of above and below, the implementation of
mem_between avoids traversing the subtrees of s that
lie entirely outside the interval of interest.
Variable above_low_bound:
elt ->
bool.
Variable below_high_bound:
elt ->
bool.
Fixpoint raw_mem_between (
m:
Raw.tree) :
bool :=
match m with
|
Raw.Leaf =>
false
|
Raw.Node _ l x r =>
if above_low_bound x
then if below_high_bound x
then true
else raw_mem_between l
else raw_mem_between r
end.
Definition mem_between (
m:
t) :
bool :=
raw_mem_between m.(
MSet.this).
Hypothesis above_monotone:
forall x1 x2,
X.eq x1 x2 \/
X.lt x1 x2 ->
above_low_bound x1 =
true ->
above_low_bound x2 =
true.
Hypothesis below_monotone:
forall x1 x2,
X.eq x1 x2 \/
X.lt x2 x1 ->
below_high_bound x1 =
true ->
below_high_bound x2 =
true.
Lemma raw_mem_between_1:
forall m,
raw_mem_between m =
true ->
exists x,
Raw.In x m /\
above_low_bound x =
true /\
below_high_bound x =
true.
Proof.
induction m;
simpl;
intros.
-
discriminate.
-
destruct (
above_low_bound t1)
eqn:
LB; [
destruct (
below_high_bound t1)
eqn:
HB |
idtac].
+
exists t1;
split;
auto.
apply Raw.IsRoot.
auto.
+
exploit IHm1;
auto.
intros [
x' [
A B]].
exists x';
split;
auto.
apply Raw.InLeft;
auto.
+
exploit IHm2;
auto.
intros [
x' [
A B]].
exists x';
split;
auto.
apply Raw.InRight;
auto.
Qed.
Lemma raw_mem_between_2:
forall x m,
Raw.bst m ->
Raw.In x m ->
above_low_bound x =
true ->
below_high_bound x =
true ->
raw_mem_between m =
true.
Proof.
Theorem mem_between_1:
forall s,
mem_between s =
true ->
exists x,
In x s /\
above_low_bound x =
true /\
below_high_bound x =
true.
Proof.
Theorem mem_between_2:
forall x s,
In x s ->
above_low_bound x =
true ->
below_high_bound x =
true ->
mem_between s =
true.
Proof.
End MEM_BETWEEN.
Section ELEMENTS_BETWEEN.
elements_between above below s returns the set of elements of s
that belong to the interval above,below.
Variable above_low_bound:
elt ->
bool.
Variable below_high_bound:
elt ->
bool.
Fixpoint raw_elements_between (
m:
Raw.tree) :
Raw.tree :=
match m with
|
Raw.Leaf =>
Raw.Leaf
|
Raw.Node _ l x r =>
if above_low_bound x then
if below_high_bound x then
Raw.join (
raw_elements_between l)
x (
raw_elements_between r)
else
raw_elements_between l
else
raw_elements_between r
end.
Remark In_raw_elements_between_1:
forall x m,
Raw.In x (
raw_elements_between m) ->
Raw.In x m.
Proof.
Lemma raw_elements_between_ok:
forall m,
Raw.bst m ->
Raw.bst (
raw_elements_between m).
Proof.
Definition elements_between (
s:
t) :
t :=
@
MSet.Mkt (
raw_elements_between s.(
MSet.this)) (
raw_elements_between_ok s.(
MSet.this)
s.(
MSet.is_ok)).
Hypothesis above_monotone:
forall x1 x2,
X.eq x1 x2 \/
X.lt x1 x2 ->
above_low_bound x1 =
true ->
above_low_bound x2 =
true.
Hypothesis below_monotone:
forall x1 x2,
X.eq x1 x2 \/
X.lt x2 x1 ->
below_high_bound x1 =
true ->
below_high_bound x2 =
true.
Remark In_raw_elements_between_2:
forall x m,
Raw.In x (
raw_elements_between m) ->
above_low_bound x =
true /\
below_high_bound x =
true.
Proof.
Remark In_raw_elements_between_3:
forall x m,
Raw.bst m ->
Raw.In x m ->
above_low_bound x =
true ->
below_high_bound x =
true ->
Raw.In x (
raw_elements_between m).
Proof.
Theorem elements_between_iff:
forall x s,
In x (
elements_between s) <->
In x s /\
above_low_bound x =
true /\
below_high_bound x =
true.
Proof.
End ELEMENTS_BETWEEN.
Section FOR_ALL_BETWEEN.
for_all_between pred above below s is true iff all elements of s
in a given variation interval satisfy predicate pred.
The variation interval is given by two predicates above and below
which must both hold if the element is part of the interval.
Using the monotonicity of above and below, the implementation of
for_all_between avoids traversing the subtrees of s that
lie entirely outside the interval of interest.
Variable pred:
elt ->
bool.
Variable above_low_bound:
elt ->
bool.
Variable below_high_bound:
elt ->
bool.
Fixpoint raw_for_all_between (
m:
Raw.tree) :
bool :=
match m with
|
Raw.Leaf =>
true
|
Raw.Node _ l x r =>
if above_low_bound x
then if below_high_bound x
then raw_for_all_between l &&
pred x &&
raw_for_all_between r
else raw_for_all_between l
else raw_for_all_between r
end.
Definition for_all_between (
m:
t) :
bool :=
raw_for_all_between m.(
MSet.this).
Hypothesis pred_compat:
forall x1 x2,
X.eq x1 x2 ->
pred x1 =
pred x2.
Hypothesis above_monotone:
forall x1 x2,
X.eq x1 x2 \/
X.lt x1 x2 ->
above_low_bound x1 =
true ->
above_low_bound x2 =
true.
Hypothesis below_monotone:
forall x1 x2,
X.eq x1 x2 \/
X.lt x2 x1 ->
below_high_bound x1 =
true ->
below_high_bound x2 =
true.
Lemma raw_for_all_between_1:
forall x m,
Raw.bst m ->
raw_for_all_between m =
true ->
Raw.In x m ->
above_low_bound x =
true ->
below_high_bound x =
true ->
pred x =
true.
Proof.
Lemma raw_for_all_between_2:
forall m,
Raw.bst m ->
(
forall x,
Raw.In x m ->
above_low_bound x =
true ->
below_high_bound x =
true ->
pred x =
true) ->
raw_for_all_between m =
true.
Proof.
induction 1;
intros;
simpl.
-
auto.
-
destruct (
above_low_bound x)
eqn:
LB; [
destruct (
below_high_bound x)
eqn:
HB |
idtac].
+
rewrite IHbst1.
rewrite (
H1 x).
rewrite IHbst2.
auto.
intros.
apply H1;
auto.
apply Raw.InRight;
auto.
apply Raw.IsRoot.
reflexivity.
auto.
auto.
intros.
apply H1;
auto.
apply Raw.InLeft;
auto.
+
apply IHbst1.
intros.
apply H1;
auto.
apply Raw.InLeft;
auto.
+
apply IHbst2.
intros.
apply H1;
auto.
apply Raw.InRight;
auto.
Qed.
Theorem for_all_between_iff:
forall s,
for_all_between s =
true <-> (
forall x,
In x s ->
above_low_bound x =
true ->
below_high_bound x =
true ->
pred x =
true).
Proof.
End FOR_ALL_BETWEEN.
Section PARTITION_BETWEEN.
Variable above_low_bound:
elt ->
bool.
Variable below_high_bound:
elt ->
bool.
Fixpoint raw_partition_between (
m:
Raw.tree) :
Raw.tree *
Raw.tree :=
match m with
|
Raw.Leaf => (
Raw.Leaf,
Raw.Leaf)
|
Raw.Node _ l x r =>
if above_low_bound x then
if below_high_bound x then
(
let (
l1,
l2) :=
raw_partition_between l in
let (
r1,
r2) :=
raw_partition_between r in
(
Raw.join l1 x r1,
Raw.concat l2 r2))
else
(
let (
l1,
l2) :=
raw_partition_between l in
(
l1,
Raw.join l2 x r))
else
(
let (
r1,
r2) :=
raw_partition_between r in
(
r1,
Raw.join l x r2))
end.
Remark In_raw_partition_between_1:
forall x m,
Raw.In x (
fst (
raw_partition_between m)) ->
Raw.In x m.
Proof.
Remark In_raw_partition_between_2:
forall x m,
Raw.In x (
snd (
raw_partition_between m)) ->
Raw.In x m.
Proof.
Lemma raw_partition_between_ok:
forall m,
Raw.bst m ->
Raw.bst (
fst (
raw_partition_between m)) /\
Raw.bst (
snd (
raw_partition_between m)).
Proof.
Hypothesis above_monotone:
forall x1 x2,
X.eq x1 x2 \/
X.lt x1 x2 ->
above_low_bound x1 =
true ->
above_low_bound x2 =
true.
Hypothesis below_monotone:
forall x1 x2,
X.eq x1 x2 \/
X.lt x2 x1 ->
below_high_bound x1 =
true ->
below_high_bound x2 =
true.
Remark In_raw_partition_between_3:
forall x m,
Raw.In x (
fst (
raw_partition_between m)) ->
above_low_bound x =
true /\
below_high_bound x =
true.
Proof.
Remark In_raw_partition_between_4:
forall x m,
Raw.bst m ->
Raw.In x (
snd (
raw_partition_between m)) ->
above_low_bound x =
false \/
below_high_bound x =
false.
Proof.
Remark In_raw_partition_between_5:
forall x m,
Raw.bst m ->
Raw.In x m ->
above_low_bound x =
true ->
below_high_bound x =
true ->
Raw.In x (
fst (
raw_partition_between m)).
Proof.
Remark In_raw_partition_between_6:
forall x m,
Raw.bst m ->
Raw.In x m ->
above_low_bound x =
false \/
below_high_bound x =
false ->
Raw.In x (
snd (
raw_partition_between m)).
Proof.
Definition partition_between (
s:
t) :
t *
t :=
let p :=
raw_partition_between s.(
MSet.this)
in
(@
MSet.Mkt (
fst p) (
proj1 (
raw_partition_between_ok s.(
MSet.this)
s.(
MSet.is_ok))),
@
MSet.Mkt (
snd p) (
proj2 (
raw_partition_between_ok s.(
MSet.this)
s.(
MSet.is_ok)))).
Theorem partition_between_iff_1:
forall x s,
In x (
fst (
partition_between s)) <->
In x s /\
above_low_bound x =
true /\
below_high_bound x =
true.
Proof.
Theorem partition_between_iff_2:
forall x s,
In x (
snd (
partition_between s)) <->
In x s /\ (
above_low_bound x =
false \/
below_high_bound x =
false).
Proof.
End PARTITION_BETWEEN.
End Make.