Require Import List.
Require Import Arith.
Require Import Freevar.
Require Import Misc.
Require Import Psatz.
Require Import Star.
Require Import Coq.Logic.Eqdep_dec.
Require Import FEnv.
Require Import STerm.
Require Import Inductive.
Infinite reduction starting from an element.
CoInductive infred {
A :
Type} (
R :
A ->
A ->
Prop) :
A ->
Prop :=
|
infred_step :
forall x y,
R x y ->
infred R y ->
infred R x.
Either divergence or finite reduction from an element to another.
CoInductive costar {
A :
Type} (
R :
A ->
A ->
Prop) :
A ->
option A ->
Prop :=
|
costar_refl :
forall x,
costar R x (
Some x)
|
costar_step :
forall x y z,
R x y ->
costar R y z ->
costar R x z.
Impredicative encoding of costar, useful for proofs.
Definition costarP {
A :
Type} (
R :
A ->
A ->
Prop)
x y :=
exists H,
H x y /\
forall x1 y1,
H x1 y1 ->
y1 =
Some x1 \/
exists z,
R x1 z /\
H z y1.
Lemmas useful for proving costar.
Lemma costarP_costar :
forall A (
R :
A ->
A ->
Prop)
x y,
costarP R x y ->
costar R x y.
Proof.
intros A R. cofix IH. intros x y (H & H1 & H2).
apply H2 in H1. destruct H1 as [H1 | (z & HR & H1)].
- subst. constructor.
- econstructor; [eassumption|]. apply IH. exists H; split; assumption.
Qed.
Lemma infred_map_impl :
forall (
A B :
Type) (
RA :
A ->
A ->
Prop) (
RB :
B ->
B ->
Prop) (
f :
A ->
B),
(
forall x y :
A,
RA x y ->
RB (
f x) (
f y)) ->
forall x :
A,
infred RA x ->
infred RB (
f x).
Proof.
intros A B RA RB f H. cofix IH. intros x Hx. inversion Hx; subst.
econstructor; [apply H; eassumption|].
apply IH. assumption.
Qed.
Lemma costar_map_impl :
forall (
A B :
Type) (
RA :
A ->
A ->
Prop) (
RB :
B ->
B ->
Prop) (
f :
A ->
B),
(
forall x y :
A,
RA x y ->
RB (
f x) (
f y)) ->
forall x y,
costar RA x y ->
costar RB (
f x) (
match y with None =>
None |
Some y =>
Some (
f y)
end).
Proof.
intros A B RA RB f H. cofix IH. intros x y Hx. inversion Hx; subst.
- constructor.
- econstructor; [apply H; eassumption|].
apply IH. assumption.
Qed.
Lemma costar_compose :
forall (
A :
Type) (
R :
A ->
A ->
Prop)
x y z,
costar R x y -> (
forall w,
y =
Some w ->
costar R w z) ->
costar R x z.
Proof.
intros A R. cofix IH. intros x y z H1 H2. inversion H1; subst.
- apply H2. reflexivity.
- econstructor; [eassumption|].
eapply IH; eassumption.
Defined.
Definition weaken {
A :
Type} (
x y :
A *
nat) :=
fst x =
fst y /\
snd y <=
snd x.
Definition weakenO {
A :
Type} (
x y :
option (
A *
nat)) :=
match x,
y with None,
None =>
True |
Some x,
Some y =>
weaken x y |
_,
_ =>
False end.
Lemma weaken_refl :
forall (
A :
Type) (
x :
A *
nat),
weaken x x.
Proof.
intros A [x y]. unfold weaken. simpl. split; reflexivity.
Qed.
Lemma weakenO_refl :
forall (
A :
Type) (
x :
option (
A *
nat)),
weakenO x x.
Proof.
intros A [x|]; unfold weakenO; simpl.
- apply weaken_refl.
- tauto.
Qed.
Definition stepped {
A :
Type} (
R :
A ->
A ->
Prop)
x y :=
R (
fst x) (
fst y) \/ (
fst x =
fst y /\
snd y <
snd x).
Definition costarPTn {
A :
Type} (
R :
A ->
A ->
Prop)
x y :=
exists H,
H x y /\
forall x1 y1,
H x1 y1 ->
weakenO (
Some x1)
y1 \/
(
exists z1,
stepped R x1 z1 /\
H z1 y1) \/
(
exists z1 z2,
stepped R x1 z1 /\
H z1 z2 /\ (
forall v,
z2 =
Some v ->
H v y1)).
Lemma costarPTn_destruct :
forall (
A :
Type) (
R :
A ->
A ->
Prop)
x y,
costarPTn R x y ->
weakenO (
Some x)
y \/
(
exists z,
stepped R x z /\
costarPTn R z y) \/
(
exists z1 z2,
stepped R x z1 /\
costarPTn R z1 z2 /\ (
forall v,
z2 =
Some v ->
costarPTn R v y)).
Proof.
intros A R x y (H & H1 & H2).
apply H2 in H1. destruct H1 as [H1 | [(z & Hz1 & Hz2) | (z1 & z2 & Hz1 & Hz2 & Hz3)]].
- left. assumption.
- right. left. exists z. split; [assumption|]. exists H; split; assumption.
- right. right. exists z1. exists z2. split; [assumption|]. split.
+ exists H; split; assumption.
+ intros v ->. exists H; split; [|assumption]. apply Hz3. reflexivity.
Qed.
Lemma weaken_trans :
forall (
A :
Type) (
x y z :
A *
nat),
weaken x y ->
weaken y z ->
weaken x z.
Proof.
intros A [x1 x2] [y1 y2] [z1 z2]; unfold weaken; simpl.
intros [? ?] [? ?]; split; [congruence|lia].
Qed.
Lemma stepped_weaken :
forall (
A :
Type) (
R :
A ->
A ->
Prop)
x y z,
weaken x y ->
stepped R y z ->
stepped R x z.
Proof.
intros A R [x1 x2] [y1 y2] [z1 z2] [H1 H2] [H3 | [H3 H4]]; simpl in *; subst.
- left; simpl; assumption.
- right; simpl; split; [reflexivity|lia].
Qed.
Lemma costarPTn_comp :
forall (
A :
Type) (
R :
A ->
A ->
Prop)
x y z,
costarPTn R x y -> (
forall v,
y =
Some v ->
costarPTn R v z) ->
costarPTn R x z.
Proof.
intros A R x y z H1 H2. exists (fun x1 y1 => costarPTn R x1 y1 \/ exists w, costarPTn R x1 w /\ (forall v, w = Some v -> costarPTn R v y1)).
split.
- right. exists y. split; assumption.
- clear x y z H1 H2. intros x z [Hxz | (y & Hxy & Hyz)].
+ apply costarPTn_destruct in Hxz. destruct Hxz as [Hxz | [(z1 & Hz1 & Hz2) | (z1 & z2 & Hz1 & Hz2 & Hz3)]].
* left. assumption.
* right. left. exists z1. split; tauto.
* right. right. exists z1. exists z2. split; [assumption|]. split; [tauto|]. intros v Hv; left; apply Hz3; assumption.
+ apply costarPTn_destruct in Hxy. destruct Hxy as [Hxy | [(z1 & Hz1 & Hz2) | (z1 & z2 & Hz1 & Hz2 & Hz3)]].
* destruct y as [y|]; simpl in *; [|tauto].
specialize (Hyz y eq_refl).
apply costarPTn_destruct in Hyz. destruct Hyz as [Hyz | [(z1 & Hz1 & Hz2) | (z1 & z2 & Hz1 & Hz2 & Hz3)]].
-- destruct z as [z|]; simpl in *; [|tauto].
left. eapply weaken_trans; eassumption.
-- right. left. exists z1. split; [eapply stepped_weaken; eassumption|].
left; assumption.
-- right. right. exists z1. exists z2. split; [eapply stepped_weaken; eassumption|].
split; [left; assumption|]. intros; left; apply Hz3; assumption.
* right. left. exists z1. split; [assumption|].
right. exists y. split; assumption.
* right. right. exists z1. exists z2. split; [assumption|].
split.
-- left; assumption.
-- intros v ->. right. exists y. split; [apply Hz3; reflexivity|].
intros w ->. apply Hyz. reflexivity.
Qed.
Lemma costarPTn_costarP :
forall (
A :
Type) (
R :
A ->
A ->
Prop)
x y,
costarPTn R x y ->
costarP R (
fst x) (
option_map fst y).
Proof.
intros A R x y H. exists (fun u v => exists n m, costarPTn R (u, n) (option_map (fun v => (v, m)) v)).
split.
- exists (snd x). exists (match y with Some y => snd y | None => 0 end).
destruct x as [x1 x2]. destruct y as [[y1 y2]|]; simpl; assumption.
- clear x y H. intros x y (n & m & H).
revert x y m H; induction n as [n Hn] using lt_wf_ind; intros x y m H.
apply costarPTn_destruct in H. destruct H as [H | [(z & Hz1 & Hz2) | (z1 & z2 & Hz1 & Hz2 & Hz3)]].
+ destruct y as [y|]; simpl in H; [|tauto].
unfold weaken in H; simpl in H. left. destruct H; congruence.
+ destruct Hz1 as [Hz1 | Hz1]; simpl in Hz1.
* right. exists (fst z). split; [assumption|].
exists (snd z). exists m. destruct z; assumption.
* destruct Hz1 as [-> Hz1]. destruct z as [z1 z2]; simpl in *.
eapply Hn; [|eassumption]. assumption.
+ destruct Hz1 as [Hz1 | Hz1]; simpl in Hz1.
* right. exists (fst z1). split; [assumption|].
exists (snd z1). exists m. eapply costarPTn_comp; [destruct z1; simpl in *; eassumption|].
eassumption.
* destruct Hz1 as [-> Hz1]. destruct z1 as [z3 z4]; simpl in *.
eapply Hn; [exact Hz1|].
eapply costarPTn_comp; eassumption.
Qed.