Require Import Coqlib.
Require Integers Pointers Errors.
Require Import BinPos List Utf8.
Require Import Values Maps.
Set Implicit Arguments.
Tactic Notation "
inv"
ident(
X) :=
inversion X;
try (
subst;
clear X).
Ltac discr :=
match goal with
|
H :
forall _,
_ <>
_ |-
_ =>
eelim H;
reflexivity
end ||
idtac.
Lemma true_neq_false :
true <>
false.
Proof.
discriminate. Qed.
Ltac tnf :=
match goal with
|
H :
true =
false |-
_ =>
elim (
true_neq_false H)
|
H :
false =
true |-
_ =>
elim (
true_neq_false (
eq_sym H))
end.
Notation "'
do'
X <-
A ;
B" := (
optbind (
fun X =>
B)
A)
(
at level 200,
X ident,
A at level 100,
B at level 200).
Definition bind2 (
A B C:
Type) (
f:
option (
A*
B)) (
g:
A ->
B ->
option C) :
option C :=
match f with Some (
a,
b) =>
g a b |
None =>
None end.
Notation "'
do' (
X ,
Y ) <-
A ;
B" := (
bind2 A (
fun X Y =>
B))
(
at level 200,
X ident,
Y ident,
A at level 100,
B at level 200).
Lemma opt_bind_inversion {
A B g f} {
b:
B} :
optbind g f =
Some b ->
exists a :
A,
f =
Some a.
Proof.
destruct f as [a|].
intros; exists a; reflexivity.
simpl; intros H; inv H.
Qed.
Lemma opt_bind_inversion' {
A B g f} :
optbind g f <> @
None B ->
exists a :
A,
f =
Some a.
Proof.
destruct f as [a|].
intros; exists a; reflexivity.
simpl; intros H. congruence .
Qed.
Ltac opt_bind_inv t :=
match goal with
|
H : @
None _ <>
optbind _ _ |-
_ =>
symmetry in H;
opt_bind_inv t
|
H :
Some _ =
optbind _ _ |-
_ =>
symmetry in H;
opt_bind_inv t
|
H :
optbind _ _ =
Some _ |-
_ =>
let H' :=
fresh "
Hbind"
in
destruct (
opt_bind_inversion H)
as [
t H'];
rewrite H'
in H;
simpl in H
|
H :
optbind _ _ <> @
None _ |-
_ =>
let H' :=
fresh "
Hbind"
in
destruct (
opt_bind_inversion'
H)
as [
t H'];
rewrite H'
in H;
simpl in H
end.
Ltac bi :=
match goal with
| [
H:
Errors.bind _ _ =
Errors.OK _ |-
_] =>
let u :=
fresh "
Hbi"
in
destruct (
Errors.bind_inversion _ _ H)
as (? &
u & ?);
clear H;
(
match goal with
| [
K:
unit |-
_] =>
destruct K
end ||
idtac)
end.
Ltac bif2 :=
match goal with
| [
H:
context [
if ?
c then _ else _] |-
_] =>
let Q :=
fresh "
Htrue"
in
case_eq c;
intros Q;
rewrite Q in H;
clarify
end.
Ltac autorw :=
match goal with
| [
H:
_ =
_ |-
_] =>
rewrite H in *
end.
Ltac autorw' :=
repeat (
progress (
autorw;
clarify)).
Tactic Notation "
app_inv" :=
match goal with
|
H :
_ ++
_ ::
nil =
_ ++
_ ::
nil |-
_ =>
destruct (
app_inj_tail _ _ _ _ H)
as [?
Hsnoc0 ?
Hsnoc];
subst;
clear H
|
H :
nil =
_ ++
_ ::
_ |-
_ =>
elim (
app_cons_not_nil _ _ _ H)
|
H :
_ ++
_ ::
_ =
nil |-
_ =>
eelim app_cons_not_nil;
symmetry;
eassumption
|
H :
_ ++
_ ::
_ =
_ ::
nil |-
_ =>
rewrite <-
app_nil_l in H;
destruct (
app_inj_tail _ _ _ _ H)
as [?
Hsnoc0 ?
Hsnoc];
subst;
clear H
end.
Lemma canap :
forall {
A l} {
e:
A} {
x f},
l ++
e ::
nil =
x::
f ->
(
l =
nil /\
f =
nil /\
x =
e)
\/ (
exists m,
l =
x::
m /\
f =
m++
e::
nil).
Proof.
induction l; simpl.
intros. inv H. left; intuition.
intros e x f H. inv H.
right. intuition eauto.
Qed.
Inductive lift_exists_list {
X Y :
Type} (
R:
X ->
Y ->
Prop) :
list X ->
Y ->
Prop :=
|
lel_hd x tl y (
HR:
R x y) :
lift_exists_list R (
x::
tl)
y
|
lel_tl hd tl y (
HR:
lift_exists_list R tl y) :
lift_exists_list R (
hd::
tl)
y
.
Lemma in_lift_exists_list {
X Y} (
R:
X ->
Y ->
Prop) :
forall y l x,
R x y ->
In x l ->
lift_exists_list R l y.
Proof.
induction l. vauto.
intros x H Q; inv Q.
vauto.
right. eauto.
Qed.
Lemma lift_exists_list_in {
X Y} (
R:
X ->
Y ->
Prop) :
forall y l,
lift_exists_list R l y ->
exists x,
R x y /\
In x l.
Proof.
induction l; intros K; inv K.
eexists; intuition eauto. intuition.
destruct (IHl HR) as [x Hx].
exists x. intuition.
Qed.
Inductive list_forall {
X :
Type} (
P:
X ->
Prop) :
list X ->
Prop :=
|
lf_nil :
list_forall P nil
|
lf_cons x l :
P x ->
list_forall P l ->
list_forall P (
x::
l)
.
Inductive lift_forall_list {
X Y :
Type} (
R:
X ->
Y ->
Prop) :
list X ->
list Y ->
Prop :=
|
lfl_nil :
lift_forall_list R nil nil
|
lfl_cons x y xl yl (
HEAD:
R x y) (
TAIL:
lift_forall_list R xl yl)
:
lift_forall_list R (
x::
xl) (
y::
yl).
Lemma in_lift_list {
X Y}
R : ∀
l l',
lift_forall_list R l l' ->
∀
x :
X,
In x l -> ∃
y :
Y, (
In y l' ∧
R x y).
Proof.
induction 1 as [|x y xl yl HEAD H HI].
intros ? K; inv K.
intros a [K|K].
subst. exists y. intuition.
destruct (HI _ K) as [b Hb].
exists b. intuition.
Qed.
Lemma lfl_snoc {
X Y} (
R:
X→
Y→
Prop) : ∀
xl yl x y,
lift_forall_list R (
xl ++
x ::
nil) (
yl ++
y ::
nil) <->
(
lift_forall_list R xl yl ∧
R x y).
Proof.
induction xl.
intros yl x y. simpl.
split. intros H; inv H; inv TAIL. destruct yl; inv H3. intuition. constructor.
app_inv.
intros [H K]; inv H. simpl. repeat constructor. assumption.
intros yl x y.
split.
destruct yl; simpl; intros H; inv H. inv TAIL. try app_inv.
destruct (IHxl yl x y) as [U _].
destruct (U TAIL); intuition. repeat constructor; trivial.
intros [H K]; inv H.
simpl.
constructor. trivial.
destruct (IHxl yl0 x y) as [_ V].
apply V. intuition.
Qed.
Lemma lfl2 A B R :
forall x y, @
list_forall2 A B R x y <-> @
lift_forall_list A B R x y.
Proof.
induction x as [|a x HI]; intros y; split; intros H; inv H; constructor; auto; apply HI; auto.
Qed.
Lemma lessdef_list_length {
l l'} :
Val.lessdef_list l l' →
length l =
length l'.
Proof.
induction 1; simpl; intuition.
Qed.
Inductive lift_opt {
X Y} (
R:
X ->
Y ->
Prop) :
option X ->
option Y ->
Prop :=
|
lo_none :
lift_opt R None None
|
lo_some x y (
HR:
R x y) :
lift_opt R (
Some x) (
Some y)
.
Hint Constructors lift_opt.
Definition list_max :=
fold_left Pmax.
Notation "
M '{{'
key '}}'" :=
(
match PTree.get key M with Some l =>
l |
None => @
nil _ end)(
at level 0,
no associativity).
Definition of_pair_list {
A} (
elt:
list (
positive *
A)) :
PTree.t A :=
fold_left
(
fun m kv =>
m ! (
fst kv) <- (
snd kv)
)
elt
(
PTree.empty A).
Fixpoint of_list' {
A} (
elt:
list A)
id :
PTree.t A :=
match elt with
|
nil =>
PTree.empty _
|
e::
elt' =>
let m :=
of_list'
elt' (
Psucc id)
in
m !
id <-
e
end.
Definition of_list {
A} (
elt:
list A) :
PTree.t A :=
of_list'
elt xH.
Section FIND_P.
Context {
A :
Type}.
Variable P :
A ->
Prop.
Hypothesis P_dec :
forall a :
A, {
P a } + { ~
P a }.
Variable t :
PTree.t A.
Definition find_p' :
option positive :=
PTree.fold (
fun res i a =>
match P_dec a with
|
left _ =>
Some i
|
right _ =>
res
end
)
t None.
Lemma find_p_correct :
match find_p'
with
|
Some i =>
match t !
i with Some a =>
P a |
None =>
False end
|
None =>
forall i a,
t !
i =
Some a -> ~
P a
end.
Proof.
unfold find_p'.
apply PTree_Properties.fold_rec.
intros m m' [
b|]
Hm Hm'.
rewrite <-
Hm.
assumption.
intros i a H.
apply (
Hm'
i).
rewrite Hm.
exact H.
intros i;
rewrite PTree.gempty.
discriminate.
intros m b k v Hk Hv.
case (
P_dec v);
intros Ha.
rewrite PTree.gss.
congruence.
destruct b as [
i|].
case (
peq i k);
intros Hb.
subst.
intros contra.
rewrite Hk in contra.
intuition.
rewrite PTree.gso;
auto.
intros H i a.
case (
peq i k);
intros Hi.
subst.
rewrite PTree.gss.
congruence.
rewrite PTree.gso;
auto.
apply H.
Qed.
Definition find_p : {
i :
positive |
match t !
i with Some a =>
P a |
None =>
False end }
+ {
forall i a,
t !
i =
Some a -> ~
P a }.
Proof.
End FIND_P.
Section REV_FIND.
Context {
A :
Type}.
Hypothesis A_eq :
forall a a' :
A, {
a =
a' } + {
a <>
a' }.
Variable t :
PTree.t A.
Definition rev_find a :
option positive :=
find_p'
_ (
A_eq a)
t.
Lemma rev_find_correct a :
match rev_find a with
|
Some i =>
t !
i =
Some a
|
None =>
forall i,
t !
i <>
Some a
end.
Proof.
unfold rev_find.
generalize (
find_p_correct _ (
A_eq a)
t).
destruct (
find_p' (
eq a) (
A_eq a)
t)
as [
i|].
destruct (
t!
i).
congruence.
intuition.
intros H i contra.
apply (
H i a contra).
reflexivity.
Qed.
End REV_FIND.
Section FORALL.
Context {
A :
Type}.
Variable P :
positive ->
A ->
Prop.
Hypothesis P_dec :
forall k (
a :
A), {
P k a } + { ~
P k a }.
Variable t :
PTree.t A.
Definition forall_spec (
F :
bool) :
Prop :=
if F
then forall k v,
t !
k =
Some v ->
P k v
else exists k,
exists v,
t !
k =
Some v /\ ~
P k v.
Definition tree_forall :
bool :=
PTree.fold
(
fun (
b:
bool)
k v =>
if b then if P_dec k v then true else false else false)
t
true.
Lemma tree_forall_correct :
forall_spec tree_forall.
Proof.
unfold forall_spec,
tree_forall.
apply PTree_Properties.fold_rec.
intros m m'
a Heq.
destruct a.
intros H k v U.
rewrite <-
Heq in U.
intuition.
intros (
k &
v &
H &
U).
exists k;
exists v.
rewrite <-
Heq.
intuition.
intros k v.
rewrite PTree.gempty.
congruence.
intros m a k v Hm Ht.
destruct a.
intros H.
destruct (
P_dec k v).
intros x y.
rewrite PTree.gsspec.
destruct (
peq x k).
subst.
congruence.
apply H.
exists k.
exists v.
rewrite PTree.gss.
intuition.
intros (
x &
y &
U &
V).
exists x.
exists y.
rewrite PTree.gsspec.
destruct (
peq x k).
congruence.
intuition.
Qed.
End FORALL.
Section FORALLB.
Context {
A:
Type}.
Variable P :
positive ->
A ->
bool.
Variable t :
PTree.t A.
Let P' :
positive ->
A ->
Prop :=
fun k a =>
P k a.
Lemma P'
_dec :
forall k a, {
P'
k a } + { ~
P'
k a }.
Proof.
subst P'.
simpl.
intros.
destruct (
P k a);
intuition. Defined.
Definition tree_forallb :
bool :=
tree_forall P'
P'
_dec t.
Corollary tree_forallb_correct :
if tree_forallb
then forall k v,
t !
k =
Some v ->
P k v
else exists k,
exists v,
t !
k =
Some v /\ ~
P k v.
Proof.
End FORALLB.
Section SUBTREE.
Context {
A :
Type}.
Variable t :
PTree.t A.
Program Fixpoint subtree'
acc id (
lst:
list positive) :
option (
PTree.t {
i :
positive |
t !
i <>
None }) :=
match lst with
|
i ::
lst' =>
do m <-
acc ;
match t !
i as H return t !
i =
H ->
_ with
|
Some _ =>
fun K =>
subtree' (
Some (
m !
id <- (
exist _ i _))) (
Psucc id)
lst'
|
None =>
fun _ =>
None
end (
eq_refl _)
|
nil =>
acc
end.
Next Obligation.
intros Q; rewrite Q in K; inversion K. Defined.
Definition subtree lst :=
subtree' (
Some (
PTree.empty _))
xH lst.
Context {
B:
Type}.
Variable f :
A ->
B.
Lemma map_subtree_prop i :
t !
i <>
None -> (
PTree.map (
fun _ =>
f)
t) !
i <>
None.
Proof.
intros H.
rewrite PTree.gmap.
destruct (
t!
i).
discriminate.
congruence. Qed.
Definition map_subtree (
s :
PTree.t {
i :
positive |
t !
i <>
None }) :
PTree.t {
i :
positive | (
PTree.map (
fun _ =>
f)
t) !
i <>
None } :=
PTree.map (
fun _ (
iH : {
i :
positive |
t !
i <>
None } ) =>
match iH with exist i H =>
exist (
fun j => (
PTree.map (
fun _ =>
f)
t) !
j <>
None)
i (
map_subtree_prop i H)
end)
s.
End SUBTREE.
Ltac tid_case tid :=
intros ?
t;
case (
peq t tid);
intros ?
Ht;
[
subst;
repeat rewrite PTree.gss|
repeat (
rewrite PTree.gso;[|
exact Ht])].
Tactic Notation "
solve_by_inversion_step"
tactic(
t) :=
match goal with
|
H :
_ |-
_ =>
solve [
inversion H;
subst;
t ]
end
||
fail "
because the goal is not solvable by inversion.".
Tactic Notation "
solve" "
by" "
inversion" "1" :=
solve_by_inversion_step idtac.
Tactic Notation "
solve" "
by" "
inversion" "2" :=
solve_by_inversion_step (
solve by inversion 1).
Tactic Notation "
solve" "
by" "
inversion" "3" :=
solve_by_inversion_step (
solve by inversion 2).
Tactic Notation "
solve" "
by" "
inversion" :=
solve by inversion 1.
Lemma last_eq {
X:
Type} : ∀
l x d,
last (
l++
x::@
nil X)
d =
x.
Proof.
induction l.
reflexivity.
intros x d.
simpl. rewrite IHl.
destruct l; reflexivity.
Qed.
Lemma last_cons {
X:
Type} :
forall b (
a c:
X),
last (
a::
b)
c =
last b a.
Proof.
induction b. reflexivity.
intros x y.
rewrite IHb.
rewrite <- IHb with a y.
reflexivity.
Qed.
David's stuff
Tactic Notation ">"
tactic(
t) :=
t.
Tactic Notation "
by"
tactic(
t) :=
t;
fail "
this goal should be proved at this point".
Ltac invh f :=
match goal with
[
id:
f |-
_ ] =>
inv id
| [
id:
f _ |-
_ ] =>
inv id
| [
id:
f _ _ |-
_ ] =>
inv id
| [
id:
f _ _ _ |-
_ ] =>
inv id
| [
id:
f _ _ _ _ |-
_ ] =>
inv id
| [
id:
f _ _ _ _ _ |-
_ ] =>
inv id
| [
id:
f _ _ _ _ _ _ |-
_ ] =>
inv id
| [
id:
f _ _ _ _ _ _ _ |-
_ ] =>
inv id
| [
id:
f _ _ _ _ _ _ _ _ |-
_ ] =>
inv id
| [
id:
f _ _ _ _ _ _ _ _ _ |-
_ ] =>
inv id
| [
id:
f _ _ _ _ _ _ _ _ _ _ |-
_ ] =>
inv id
| [
id:
f _ _ _ _ _ _ _ _ _ _ _ |-
_ ] =>
inv id
| [
id:
f _ _ _ _ _ _ _ _ _ _ _ _ |-
_ ] =>
inv id
| [
id:
f _ _ _ _ _ _ _ _ _ _ _ _ _ |-
_ ] =>
inv id
| [
id:
f _ _ _ _ _ _ _ _ _ _ _ _ _ _ |-
_ ] =>
inv id
end.
End David's stuff
Require Import Coqlib.
Section MAPS.
Local Open Scope positive_scope.
Context {
A:
Type}.
Variable q :
PTree.t A.
Lemma list_max_correct : ∀
l x z, (
In x l ∨
Ple x z) →
Ple x (
list_max l z).
Proof.
induction l as [|
p l HI].
intros x z [
H|
H].
inv H.
simpl.
exact H.
intros x z.
simpl.
intros [ [
H|
H]|
H].
subst.
apply HI.
right.
unfold Ple.
rewrite Zpos_max.
apply Zmax_bound_r.
intuition.
apply HI.
left.
assumption.
apply HI;
clear HI.
right.
unfold Ple in *.
rewrite Zpos_max.
apply Zmax_bound_l.
exact H.
Qed.
Lemma list_max_bound : ∀
l x z,
Plt (
list_max l z)
x → (~
In x l) ∧
Plt z x.
Proof.
Definition max_key :
positive :=
PTree.fold (
fun acc k _ =>
Pmax acc k)
q xH.
Lemma max_key_correct : ∀
k,
Plt max_key k →
PTree.get k q =
None.
Proof.
unfold max_key.
rewrite PTree.fold_spec.
rewrite <-
fold_left_map.
intros k H.
case_eq (
PTree.get k q). 2:
trivial.
intros a Ha.
assert (
K:=
PTree.elements_correct q k Ha).
assert (
K':=
in_map (@
fst _ _)
_ _ K).
simpl in K'.
destruct (
list_max_bound _ _ H)
as [
V W].
elim V.
exact K'.
Qed.
End MAPS.
Section TREE_MAP_PARTIAL.
Context {
A B:
Type}.
Variable f :
positive ->
A ->
Errors.res B.
Definition ptree_map_partial (
t:
PTree.t A) :
Errors.res (
PTree.t B) :=
PTree.fold
(
fun q k a =>
Errors.bind q
(
fun x =>
Errors.bind (
f k a)
(
fun y =>
Errors.OK (
x !
k <-
y))))
t
(
Errors.OK (
PTree.empty B)).
Lemma ptree_map_partial_spec t :
match ptree_map_partial t with
|
Errors.OK t' =>
(
forall k a,
t !
k =
Some a ->
exists b,
f k a =
Errors.OK b /\
t' !
k =
Some b) /\
(
forall k,
t !
k =
None ->
t' !
k =
None)
|
Errors.Error msg =>
exists k,
exists a,
t !
k =
Some a /\
f k a =
Errors.Error msg
end.
Proof.
unfold ptree_map_partial.
apply PTree_Properties.fold_rec.
intros m m' [
a|
msg]
Heq H.
destruct H as [
H H'].
split.
intros k u Hu.
rewrite <- (
Heq k)
in Hu.
destruct (
H k u Hu)
as (
b &
Hb &
Ht').
now intuition eauto.
intros k Hk.
rewrite <-
Heq in Hk.
now intuition.
destruct H as (
k &
a &
U &
V).
exists k.
exists a.
intuition congruence.
split;
intros;
rewrite PTree.gempty in *;
now intuition.
intros m [
t'|
msg]
k v Hmk Htk IH;
simpl.
destruct IH as [
IH IH'].
case_eq (
f k v);
intros b Hb;
simpl.
split.
intros k'
a'.
rewrite PTree.gsspec.
case (
peq k'
k).
intros;
clarify.
exists b.
intuition.
rewrite PTree.gss.
reflexivity.
intros Hkk Hk'.
destruct (
IH k'
_ Hk')
as (
b' &
Hb' &
K).
exists b'.
intuition.
rewrite PTree.gso;
now trivial.
intros k'.
repeat rewrite PTree.gsspec.
case (
peq k'
k);
clarify.
intuition.
exists k.
exists v.
intuition.
rewrite PTree.gss.
reflexivity.
destruct IH as (
u &
w &
H &
K).
exists u.
exists w.
intuition.
rewrite PTree.gso.
trivial.
intros contra;
subst.
congruence.
Qed.
Corollary ptree_map_partial_ok {
t t'} :
ptree_map_partial t =
Errors.OK t' ->
(
forall k a,
t !
k =
Some a ->
exists b,
f k a =
Errors.OK b /\
t' !
k =
Some b) /\
(
forall k,
t !
k =
None ->
t' !
k =
None).
Proof.
Corollary ptree_map_partial_ko {
t msg} :
ptree_map_partial t =
Errors.Error msg ->
exists k,
exists a,
t !
k =
Some a /\
f k a =
Errors.Error msg.
Proof.
Corollary ptree_map_partial_inv {
t t'} :
ptree_map_partial t =
Errors.OK t' ->
forall k b,
t' !
k =
Some b ->
exists a,
t !
k =
Some a /\
f k a =
Errors.OK b.
Proof.
generalize (
ptree_map_partial_spec t).
destruct (
ptree_map_partial t);
clarify.
intros (
H &
Q) ?;
clarify.
intros k b Hb.
case_eq (
t !
k).
intros a Ha;
eexists;
intuition.
destruct (
H k a Ha)
as (
b' &
Hab &
Hb');
rewrite Hb'
in Hb;
clarify.
intros H'.
pose proof (
Q k H').
rewrite Hb in *.
clarify.
Qed.
End TREE_MAP_PARTIAL.
Section TREE_OPT_MAP.
Context {
A B :
Type}.
Variable f :
A ->
option B.
Variable t :
PTree.t A.
Definition ptree_opt_map :
PTree.t B :=
PTree.fold (
fun res k a =>
match f a with Some b =>
res !
k <-
b |
None =>
res end)
t (
PTree.empty B).
Lemma ptree_opt_map_spec :
forall k,
match t !
k,
ptree_opt_map !
k with
|
None,
None =>
True
|
None,
_ =>
False
|
Some a,
b =>
f a =
b
end.
Proof.
intros.
unfold ptree_opt_map.
apply PTree_Properties.fold_rec.
intros m m'
a H H0.
rewrite <-
H.
trivial.
repeat rewrite PTree.gempty.
trivial.
intros m a k0 v H H0 H1.
rewrite PTree.gsspec.
destruct (
peq k k0).
subst.
rewrite H in H1.
case_eq (
f v).
intros.
rewrite PTree.gss.
trivial.
destruct (
a !
k0);
intuition.
destruct (
m !
k);
destruct (
f v);
trivial.
rewrite PTree.gso;
trivial.
rewrite PTree.gso;
trivial.
Qed.
End TREE_OPT_MAP.
Module Rset.
Definition t :=
PTree.t unit.
Local Notation elt :=
positive.
Definition empty :
t :=
PTree.empty _.
Definition add (
x:
elt) (
s:
t) :
t :=
PTree.set x tt s.
Definition singleton (
x:
elt) :
t :=
add x empty.
Definition remove (
x:
elt) (
s:
t) :
t :=
PTree.remove x s.
Definition add_list (
l:
list elt) (
s:
t) :
t :=
List.fold_right add s l.
Definition remove_list (
l:
list elt) (
s:
t) :
t :=
List.fold_right remove s l.
Definition mem (
x:
elt) (
s:
t) :
bool :=
match PTree.get x s with
|
None =>
false
|
Some _ =>
true
end.
Definition union (
s1 s2:
t) :
t :=
PTree.combine (
fun o1 o2 =>
match o1,
o2 with
|
None,
None =>
None
|
_,
_ =>
Some tt
end)
s1 s2.
Definition inter (
s1 s2:
t) :
t :=
PTree.combine (
fun o1 o2 =>
match o1,
o2 with
|
Some _,
Some _ =>
Some tt
|
_,
_ =>
None
end)
s1 s2.
Definition forallb (
f:
elt->
bool) (
s:
t) :
bool :=
PTree.fold (
fun b x _ =>
b &&
f x)
s true.
Definition subset (
r s:
t) :
bool :=
forallb (
fun x =>
mem x s)
r.
Section PROP.
Lemma add_mem {
s v} :
mem v (
add v s).
Proof.
unfold mem, add. rewrite PTree.gss. trivial. Qed.
Lemma add_mem_o {
s v v'} :
v <>
v' ->
mem v (
add v'
s) =
mem v s.
Proof.
unfold mem, add. intros K. rewrite PTree.gsspec. destruct (peq v v'); clarify. Qed.
Lemma mem_add {
s v v'} :
mem v s ->
mem v (
add v'
s).
Proof.
unfold mem, add. intros K. rewrite PTree.gsspec. destruct peq; clarify. Qed.
Lemma add_comm {
s v v'} :
add v (
add v'
s) =
add v' (
add v s).
Proof.
apply PTree.ext. intros x. unfold add. repeat rewrite PTree.gsspec.
destruct (peq x v); destruct (peq x v'); reflexivity.
Qed.
Lemma add_not_empty {
s v} :
add v s <>
empty.
Proof.
unfold add,
empty.
intros K.
assert (
Some tt <>
None)
as Q by discriminate.
elim Q.
replace (
Some tt)
with ((
s !
v <-
tt) !
v).
rewrite K.
apply PTree.gempty.
apply PTree.gss.
Qed.
Lemma mem_add_nop {
s v} :
mem v s ->
add v s =
s.
Proof.
unfold mem, add. intros K.
apply PTree.ext. intros x. rewrite PTree.gsspec.
destruct (peq x v). subst. destruct (s ! v) as [[]|]; clarify. trivial.
Qed.
Lemma remove_comm {
s v v'} :
remove v (
remove v'
s) =
remove v' (
remove v s).
Proof.
unfold remove. apply PTree.ext.
intros x; repeat rewrite PTree.grspec.
destruct (PTree.elt_eq x v); destruct (PTree.elt_eq x v'); trivial.
Qed.
Lemma remove_add {
s v} : ~
mem v s ->
remove v (
add v s) =
s.
Proof.
unfold mem, remove, add. intros K.
apply PTree.ext. intros. rewrite PTree.grspec.
destruct (PTree.elt_eq x v).
subst. destruct (s ! v); clarify.
exploit PTree.gso; eauto.
Qed.
Lemma remove_add_remove {
s v} :
remove v (
add v s) =
remove v s.
Proof.
unfold mem, remove, add.
apply PTree.ext. intros. rewrite PTree.grspec.
destruct (PTree.elt_eq x v).
subst. rewrite PTree.grs; auto.
rewrite PTree.gro; auto.
exploit PTree.gso; eauto.
Qed.
Lemma add_remove {
s v} :
add v (
remove v s) =
add v s.
Proof.
unfold remove, add.
apply PTree.ext. intros. repeat rewrite PTree.gsspec.
destruct (peq x v). trivial.
rewrite PTree.grspec.
destruct (PTree.elt_eq x v); clarify.
Qed.
Lemma not_mem_remove_nop {
s v} : ~
mem v s ->
remove v s =
s.
Proof.
unfold mem, remove. intros K.
apply PTree.ext. intros x. rewrite PTree.grspec.
destruct (PTree.elt_eq x v). subst. destruct (s ! v) as [[]|]; clarify. trivial.
Qed.
Lemma remove_not_mem {
v s} : ¬
mem v (
remove v s).
Proof.
unfold mem, remove. rewrite PTree.grs. clarify. Qed.
Lemma mem_rmo {
s v v'} :
v <>
v' ->
mem v (
remove v'
s) =
mem v s.
Proof.
unfold mem, remove. intros K.
rewrite PTree.grspec.
destruct (PTree.elt_eq v v'); clarify.
Qed.
Lemma empty_not_mem {
v} : ~
mem v empty.
Proof.
unfold mem, empty. rewrite PTree.gempty. intuition. Qed.
Context {
f :
elt ->
bool }.
Lemma forallb_spec r :
match forallb f r with
|
true =>
forall x,
mem x r ->
f x
|
false =>
exists x,
mem x r /\ ~
f x
end.
Proof.
unfold forallb,
mem.
apply PTree_Properties.fold_rec.
>
intros m m' []
H H0.
intros x K.
rewrite <-
H in K.
intuition.
destruct H0 as (
x &
Hx).
exists x.
rewrite <-
H.
assumption.
>
intros x.
rewrite PTree.gempty.
congruence.
>
intros m []
k v H H0 H1.
>
simpl.
case_eq (
f k);
intros Hfk.
>
intros x.
rewrite PTree.gsspec.
destruct (
peq x k).
subst.
intuition.
intuition.
>
exists k.
rewrite PTree.gss.
intuition.
congruence.
>
simpl.
destruct H1 as (
x &
Hx).
exists x.
rewrite PTree.gso.
assumption.
intros contra;
subst.
rewrite H in Hx.
intuition.
Qed.
Corollary forallb_forall {
x r} :
forallb f r ->
mem x r ->
f x.
Proof.
intros H.
generalize (
forallb_spec r).
rewrite H.
intuition. Qed.
Corollary forall_forallb {
r} :
(∀
x,
mem x r →
f x) →
forallb f r.
Proof.
intros H.
generalize (
forallb_spec r).
destruct (
forallb f r).
easy.
intros (
x &
K &
Q).
specialize H with x.
intuition.
Qed.
End PROP.
Lemma subset_spec {
r s} :
subset r s <-> ∀
x,
mem x r →
mem x s.
Proof.
Remark empty_subset {
r} :
subset empty r.
Proof.
auto. Qed.
Lemma subset_refl {
r} :
subset r r.
Proof.
Lemma subset_trans :
transitive _ subset.
Proof.
Lemma subset_antisym :
antisymmetric _ subset.
Proof.
intros x y X Y.
apply PTree.ext.
intros q.
case_eq (
x !
q).
intros ()
Qx.
assert (
mem q y).
eapply (
forallb_forall X).
unfold mem.
autorw'.
unfold mem in *.
destruct (
y !
q)
as [()|];
clarify.
intros Qx.
case_eq (
y !
q).
intros ()
Qy.
assert (
mem q x).
eapply (
forallb_forall Y).
unfold mem.
autorw'.
unfold mem in *.
autorw'.
easy.
Qed.
Remark subset_empty {
r} :
subset r empty →
r =
empty.
Proof.
Lemma mem_singleton {
x y} :
mem x (
singleton y) →
x =
y.
Proof.
unfold singleton.
case (
peq x y).
easy.
intros K H.
rewrite add_mem_o in H.
eelim empty_not_mem;
eassumption.
easy.
Qed.
Lemma subset_singleton : ∀
r x,
subset r (
singleton x) →
r =
empty ∨
r =
singleton x.
Proof.
Lemma remove_subset {
x r} :
subset (
remove x r)
r.
Proof.
Lemma subset_add {
v s} :
subset s (
add v s).
Proof.
Lemma add_singleton {
v v'
s} :
add v s =
singleton v' →
v =
v' ∧
subset s (
singleton v).
Proof.
Lemma remove_last {
v s} :
remove v s =
empty →
subset s (
singleton v).
Proof.
Lemma add_remove_comm {
v v'
s} :
v ≠
v' →
remove v' (
add v s) =
add v (
remove v'
s).
Proof.
End Rset.
Section list.
Context {
A:
Type}.
Lemma In_eq_app:
forall (
x:
A)
l,
In x l ->
exists l1,
exists l2,
l =
l1++
x::
l2.
Proof.
induction l;
intros;
inv H.
exists nil;
simpl;
econstructor;
reflexivity.
destruct IHl as (
l1 &
l2 &
Hl);
auto.
exists (
a::
l1);
exists l2;
subst;
auto.
Qed.
Lemma eq_app_app:
forall (
a b:
A)
l1 l2 l3 l4,
l1 ++
a ::
l2 =
l3 ++
b ::
l4 ->
a<>
b ->
(
exists l,
l1 =
l3 ++
b ::
l /\
l4 =
l ++
a ::
l2)
\/
(
exists l,
l3 =
l1 ++
a ::
l /\
l2 =
l ++
b ::
l4).
Proof.
induction l1; destruct l3; simpl; intros.
inv H; intuition.
inv H; right; exists l3; auto.
inv H; left; exists l1; auto.
inv H.
exploit IHl1; eauto; intros [(l & L1 & L2) | (l & L1 & L2)]; subst; clear IHl1.
left; econstructor; split; eauto.
right; econstructor; split; eauto.
Qed.
End list.
Reserved Notation "
m ¡
l" (
no associativity,
at level 60).
Fixpoint get_list {
X:
Type} (
m:
PTree.t X) (
l:
list positive)
:
option (
list X) :=
match l with
|
nil =>
Some nil
|
p::
l' =>
do x <-
m !
p ;
do r <-
m ¡
l';
Some (
x ::
r)
end
where "
m ¡
l" := (
get_list m l).
Fixpoint fold_left2 {
A B C:
Type} (
f:
A →
B →
C →
A) (
z:
A) (
u:
list B) (
v:
list C) :
A :=
match u,
v with
|
b::
u',
c::
v' =>
fold_left2 f (
f z b c)
u'
v'
|
_,
_ =>
z
end.
Fixpoint fold_right2 {
A B C:
Type} (
f:
A →
B →
C →
A) (
z:
A) (
u:
list B) (
v:
list C) :
A :=
match u,
v with
|
b::
u',
c::
v' =>
f (
fold_right2 f z u'
v')
b c
|
_,
_ =>
z
end.
Class EqDec {
X:
Type} :=
{
eq_dec: ∀
x y:
X, {
x =
y } + {
x ≠
y }
}.
Definition upd `{
X:
Type} `{
EqDec X} {
Y} (
f:
X →
Y)
p (
v:
Y) :=
fun q =>
if eq_dec p q then v else f q.
Lemma upd_s `{
X:
Type} `{
EqDec X} {
Y} (
f:
X →
Y)
p v:
(
upd f p v)
p =
v.
Proof.
unfold upd.
case (
eq_dec p p);
tauto. Qed.
Lemma upd_o `{
X:
Type} `{
EqDec X} {
Y} (
f:
X →
Y)
p v p' :
p ≠
p' → (
upd f p v)
p' =
f p'.
Proof.
unfold upd.
case (
eq_dec p p');
tauto. Qed.
Ltac eq_case :=
match goal with |-
appcontext[ @
eq_dec _ _ ?
x ?
y ] =>
case (
eq_dec x y)
end.
Instance ZEqDec : @
EqDec Z :=
Build_EqDec Z_eq_dec.
Instance PosEqDec : @
EqDec positive :=
Build_EqDec peq.
Instance IntEqDec : @
EqDec Integers.int :=
Build_EqDec _.
Proof.
intros x y; generalize (Integers.Int.eq_spec x y).
now destruct (Integers.Int.eq x y); auto.
Defined.
Instance PtrEqDec : @
EqDec Pointers.pointer :=
Build_EqDec _.
Proof.
intros [
u i] [
v j].
case (
eq_dec u v).
intros <-.
case (
eq_dec i j).
now intros <-;
left.
intros K;
right;
intros L.
clarify.
right;
intros ?;
clarify.
Defined.
Section OPT_MAP.
Context {
A B:
Type}.
Variable (
f:
A →
option B).
Definition opt_map' (
l:
list A) :
option (
list B) →
option (
list B) :=
fold_left (
fun l a =>
do b <-
f a;
do l' <-
l;
Some (
b::
l'))
l.
Definition opt_map (
l:
list A) :
option (
list B) :=
opt_map'
l (
Some nil).
Lemma opt_map'
_none l:
opt_map'
l None =
None.
Proof.
induction l as [|
x l IH].
reflexivity.
simpl.
case (
f x);
easy.
Qed.
Lemma opt_map_none (
l:
list A) :
opt_map l =
None → ∃
a,
In a l ∧
f a =
None.
Proof.
unfold opt_map.
generalize ((@
nil B)).
induction l as [|
a l IH].
inversion 1.
simpl.
case_eq (
f a);
simpl.
intros b Hb.
intros m Hm.
destruct (
IH _ Hm)
as [
x (
H &
K)].
exists x.
tauto.
intros H m Hb.
exists a.
tauto.
Qed.
Lemma opt_map_some (
l:
list A) :
opt_map l ≠
None → ∀
a,
In a l →
f a ≠
None.
Proof.
unfold opt_map.
generalize (@
nil B).
induction l as [|
a l IH].
tauto.
simpl.
case_eq (
f a);
simpl.
intros b Hb.
intros m Hm u [->|
Hu].
congruence.
now eapply IH;
eauto.
rewrite opt_map'
_none.
congruence.
Qed.
End OPT_MAP.
Ltac andb'
a b :=
match goal with
| [
H:
is_true (
_ &&
_) |-
_ ] =>
unfold is_true in H;
andb'
a b
| [
H:
_ &&
_ =
true |-
_ ] =>
apply andb_true_iff in H;
destruct H as [
a b]
end.
Tactic Notation "
andb" "
as"
ident(
a)
ident(
b) :=
andb'
a b.
Tactic Notation "
andb" :=
let a :=
fresh "
L"
in let b :=
fresh "
R"
in andb'
a b.