Module Rewrite

Require Import List.
Require Import Arith.
Require Import Misc.
Require Import Psatz.

Definition curry {A B C : Type} (f : A * B -> C) x y := f (x, y).
Definition uncurry {A B C : Type} (f : A -> B -> C) '(x, y) := f x y.
Definition flip {A B C : Type} (f : A -> B -> C) x y := f y x.
Definition union {A B : Type} (R1 R2 : A -> B -> Prop) x y := R1 x y \/ R2 x y.
Definition compose {A B C : Type} (R1 : A -> B -> Prop) (R2 : B -> C -> Prop) x y := exists z, R1 x z /\ R2 z y.

Definition same_rel {A B : Type} (R1 R2 : A -> B -> Prop) :=
  forall x y, R1 x y <-> R2 x y.

Lemma same_rel_refl {A : Type} (R : A -> A -> Prop) : same_rel R R.
Proof.   intros x y. reflexivity.
Qed.

Lemma same_rel_sym {A B : Type} (R1 R2 : A -> B -> Prop) :
  same_rel R1 R2 -> same_rel R2 R1.
Proof.   intros H x y; split; intros H1; apply H; assumption.
Qed.

Lemma same_rel_trans {A B : Type} (R1 R2 R3 : A -> B -> Prop) :
  same_rel R1 R2 -> same_rel R2 R3 -> same_rel R1 R3.
Proof.   intros H1 H2 x y; split; intros H3; [apply H2, H1, H3|apply H1, H2, H3].
Qed.

Lemma flip_flip :
  forall (A B : Type) (R : A -> B -> Prop), same_rel (flip (flip R)) R.
Proof.   intros A R x y. reflexivity.
Qed.


Reflexive closure

Definition reflc {A : Type} (R : A -> A -> Prop) x y := R x y \/ x = y.

Lemma same_rel_reflc {A : Type} (R1 R2 : A -> A -> Prop) :
  same_rel R1 R2 -> same_rel (reflc R1) (reflc R2).
Proof.   intros H x y.
  split; intros [Hxy | ->]; try (right; reflexivity); left; apply H; assumption.
Qed.


Symmetric closure
Definition symc {A : Type} (R : A -> A -> Prop) := union R (flip R).

Lemma symc_sym {A : Type} (R : A -> A -> Prop) :
  forall x y, symc R x y -> symc R y x.
Proof.   intros x y [H | H]; [right | left]; assumption.
Qed.


Transitive reflexive closure

Inductive star {A : Type} (R : A -> A -> Prop) : A -> A -> Prop :=
| star_refl : forall x, star R x x
| star_step : forall x y z, R x y -> star R y z -> star R x z.

Lemma star_1 {A : Type} (R : A -> A -> Prop) :
  forall x y, R x y -> star R x y.
Proof.   intros x y H. econstructor; [eassumption|].
  constructor.
Qed.

Lemma star_compose :
  forall (A : Type) (R : A -> A -> Prop) x y z, star R x y -> star R y z -> star R x z.
Proof.   intros A R x y z H. induction H.
  - intros; assumption.
  - intros; econstructor; [eassumption | firstorder].
Qed.

Lemma star_map_impl :
  forall (A B : Type) (RA : A -> A -> Prop) (RB : B -> B -> Prop) (f : A -> B),
    (forall x y, RA x y -> RB (f x) (f y)) -> forall x y, star RA x y -> star RB (f x) (f y).
Proof.   intros A B RA RB f HR x y H. induction H.
  - constructor.
  - econstructor; eauto.
Qed.

Lemma star_impl :
  forall (A : Type) (R1 R2 : A -> A -> Prop),
    (forall x y, R1 x y -> R2 x y) -> forall x y, star R1 x y -> star R2 x y.
Proof.   intros A R1 R2 H x y Hxy. eapply star_map_impl with (f := id); eassumption.
Qed.

Lemma same_rel_star {A : Type} (R1 R2 : A -> A -> Prop) :
  same_rel R1 R2 -> same_rel (star R1) (star R2).
Proof.   intros H x y.
  split; intros Hxy; eapply star_impl; try eassumption; intros; apply H; assumption.
Qed.

Lemma star_preserve :
  forall {A : Type} (R : A -> A -> Prop) (P : A -> Prop), (forall x y, R x y -> P x -> P y) -> forall x y, P x -> star R x y -> P y.
Proof.   intros A R P H x y Hx Hxy. induction Hxy.
  - assumption.
  - eapply IHHxy, H, Hx. apply H0.
Qed.

Lemma flip_star :
  forall (A : Type) (R : A -> A -> Prop) x y, star (flip R) x y -> star R y x.
Proof.   intros A R x y H. induction H.
  - apply star_refl.
  - eapply star_compose; [eassumption|]. apply star_1; assumption.
Qed.

Lemma flip_star_iff :
  forall (A : Type) (R : A -> A -> Prop), same_rel (star (flip R)) (flip (star R)).
Proof.   intros A R x y; split; intros H.
  - apply flip_star. assumption.
  - eapply flip_star, same_rel_star; [|eassumption]. apply flip_flip.
Qed.

Lemma star_star :
  forall (A : Type) (R : A -> A -> Prop), forall x y, star (star R) x y -> star R x y.
Proof.   intros A R x y H. induction H.
  - constructor.
  - eapply star_compose; eauto.
Qed.

Lemma star_induction_rev :
  forall {A : Type} (R : A -> A -> Prop) (P : A -> Prop) (x : A),
    P x -> (forall y z, P y -> R y z -> P z) -> (forall y, star R x y -> P y).
Proof.   intros A R P x HPx HPind y Hy. revert HPx.
  induction Hy; firstorder.
Qed.

Lemma star_same :
  forall (A : Type) (R : A -> A -> Prop) t1 t2, t1 = t2 -> star R t1 t2.
Proof.   intros A R t1 t2 ->. constructor.
Qed.

Lemma star_sym {A : Type} (R : A -> A -> Prop) (Hsym : forall x y, R x y -> R y x) :
  forall x y, star R x y -> star R y x.
Proof.   intros x y H; induction H.
  - apply star_refl.
  - eapply star_compose; [eassumption|apply star_1, Hsym; assumption].
Qed.

Lemma reflc_star {A : Type} (R : A -> A -> Prop) :
  forall x y, reflc R x y -> star R x y.
Proof.   intros x y [Hxy | <-]; [apply star_1; assumption|constructor].
Qed.

Lemma star_reflc {A : Type} (R : A -> A -> Prop) :
  same_rel (star R) (star (reflc R)).
Proof.   intros x y. split; intros H.
  - eapply star_impl; [|eassumption].
    intros; left; assumption.
  - induction H.
    + constructor.
    + destruct H as [H | ->].
      * econstructor; eassumption.
      * assumption.
Qed.

Transitive closure

Inductive plus {A : Type} (R : A -> A -> Prop) : A -> A -> Prop :=
| plus_1 : forall x y, R x y -> plus R x y
| plus_S : forall x y z, R x y -> plus R y z -> plus R x z.

Lemma plus_map_impl :
  forall (A B : Type) (RA : A -> A -> Prop) (RB : B -> B -> Prop) (f : A -> B),
    (forall x y, RA x y -> RB (f x) (f y)) -> forall x y, plus RA x y -> plus RB (f x) (f y).
Proof.   intros A B RA RB f HR x y H. induction H.
  - apply plus_1; auto.
  - eapply plus_S; eauto.
Qed.

Lemma plus_impl :
  forall (A : Type) (R1 R2 : A -> A -> Prop),
    (forall x y, R1 x y -> R2 x y) -> forall x y, plus R1 x y -> plus R2 x y.
Proof.   intros A R1 R2 H x y Hxy. eapply plus_map_impl with (f := id); eassumption.
Qed.

Lemma same_rel_plus :
  forall (A : Type) (R1 R2 : A -> A -> Prop), same_rel R1 R2 -> same_rel (plus R1) (plus R2).
Proof.   intros A R1 R2 H x y. split; intros Hplus; eapply plus_impl; try eassumption; intros; apply H; assumption.
Qed.

Lemma plus_star :
  forall (A : Type) (R : A -> A -> Prop) x y, plus R x y -> star R x y.
Proof.   intros A R x y H; induction H.
  - apply star_1. assumption.
  - econstructor; eassumption.
Qed.

Lemma plus_star_iff :
  forall (A : Type) (R : A -> A -> Prop), same_rel (plus R) (compose R (star R)).
Proof.   intros A R x y; split; intros H.
  - inversion H; subst.
    + exists y; split; [assumption|apply star_refl].
    + exists y0. split; [assumption|apply plus_star; assumption].
  - destruct H as (z & Hxz & Hzy).
    revert x Hxz; induction Hzy; intros w Hw.
    + apply plus_1; assumption.
    + eapply plus_S; [eassumption|apply IHHzy; assumption].
Qed.

Lemma plus_compose_star_left :
  forall (A : Type) (R : A -> A -> Prop) x y z, star R x y -> plus R y z -> plus R x z.
Proof.   intros A R x y z H1 H2; induction H1; [assumption|].
  econstructor; [eassumption|].
  apply IHstar; assumption.
Qed.

Lemma flip_plus :
  forall (A : Type) (R : A -> A -> Prop) x y, plus (flip R) x y -> plus R y x.
Proof.   intros A R x y H. induction H.
  - apply plus_1. assumption.
  - eapply plus_compose_star_left; [eapply plus_star; eassumption|].
    apply plus_1. assumption.
Qed.

Lemma flip_plus_iff :
  forall (A : Type) (R : A -> A -> Prop), same_rel (plus (flip R)) (flip (plus R)).
Proof.   intros A R x y; split; intros H.
  - apply flip_plus. assumption.
  - eapply flip_plus, same_rel_plus; [|eassumption]. apply flip_flip.
Qed.

Lemma plus_compose_star_right :
  forall (A : Type) (R : A -> A -> Prop) x y z, plus R x y -> star R y z -> plus R x z.
Proof.   intros A R x y z H1 H2.
  apply flip_plus_iff.
  eapply plus_compose_star_left; [|apply flip_plus_iff; eassumption].
  apply flip_star in H2. eassumption.
Qed.


Transitive symmetric reflexive closure

Definition convertible {A : Type} (R : A -> A -> Prop) := star (symc R).

Lemma convertible_refl {A : Type} (R : A -> A -> Prop) x : convertible R x x.
Proof.   intros; apply star_refl.
Qed.

Lemma convertible_sym {A : Type} (R : A -> A -> Prop) :
  forall x y, convertible R x y -> convertible R y x.
Proof.   apply star_sym, symc_sym.
Qed.

Lemma common_reduce_convertible :
  forall (A : Type) (R : A -> A -> Prop) x y z, star R x z -> star R y z -> convertible R x y.
Proof.   intros A R x y z Hxz Hyz.
  eapply star_compose.
  - eapply star_impl; [|eassumption]. intros; left; assumption.
  - eapply star_impl; [|apply flip_star_iff; eassumption]. intros; right; assumption.
Qed.



Confluence

Definition commuting_diamond {A : Type} (R1 R2 : A -> A -> Prop) :=
  forall x y z, R1 x y -> R2 x z -> exists w, R2 y w /\ R1 z w.

Definition strongly_commute {A : Type} (R1 R2 : A -> A -> Prop) :=
  forall x y z, R1 x y -> R2 x z -> exists w, reflc R2 y w /\ star R1 z w.

Definition commute {A : Type} (R1 R2 : A -> A -> Prop) := commuting_diamond (star R1) (star R2).

Definition diamond {A : Type} (R : A -> A -> Prop) := commuting_diamond R R.

Definition confluent {A : Type} (R : A -> A -> Prop) := diamond (star R).

Lemma commuting_diamond_symmetric {A : Type} (R1 R2 : A -> A -> Prop) :
  commuting_diamond R1 R2 -> commuting_diamond R2 R1.
Proof.   intros H x y z H2 H1. destruct (H x z y H1 H2) as (w & Hw2 & Hw1).
  exists w. split; assumption.
Qed.

Lemma commute_symmetric {A : Type} (R1 R2 : A -> A -> Prop) :
  commute R1 R2 -> commute R2 R1.
Proof.   intros. apply commuting_diamond_symmetric. assumption.
Qed.

Lemma commuting_diamond_ext {A : Type} (R1a R2a R1b R2b : A -> A -> Prop) :
    same_rel R1a R1b -> same_rel R2a R2b -> commuting_diamond R1a R2a <-> commuting_diamond R1b R2b.
Proof.   intros Heq1 Heq2; split; intros H x y z Hxy Hxz.
  - apply Heq1 in Hxy. apply Heq2 in Hxz. destruct (H _ _ _ Hxy Hxz) as (w & Hyw & Hzw).
    exists w; split; [apply Heq2 | apply Heq1]; assumption.
  - apply Heq1 in Hxy; apply Heq2 in Hxz. destruct (H _ _ _ Hxy Hxz) as (w & Hyw & Hzw).
    exists w; split; [apply Heq2 | apply Heq1]; assumption.
Qed.

Lemma diamond_ext {A : Type} (R1 R2 : A -> A -> Prop) :
  same_rel R1 R2 -> diamond R1 <-> diamond R2.
Proof.   intros Heq; apply commuting_diamond_ext; assumption.
Qed.

Lemma commute_ext {A : Type} (R1a R2a R1b R2b : A -> A -> Prop) :
  same_rel R1a R1b -> same_rel R2a R2b -> commute R1a R2a <-> commute R1b R2b.
Proof.   intros Heq1 Heq2. apply commuting_diamond_ext; apply same_rel_star; assumption.
Qed.

Lemma confluent_ext {A : Type} (R1 R2 : A -> A -> Prop) :
  same_rel R1 R2 -> confluent R1 <-> confluent R2.
Proof.   intros H; apply commute_ext; assumption.
Qed.

Lemma commuting_diamond_strongly_commutes {A : Type} (R1 R2 : A -> A -> Prop) :
  commuting_diamond R1 R2 -> strongly_commute R1 R2.
Proof.   intros H x y z Hxy Hxz.
  destruct (H x y z Hxy Hxz) as (w & Hw2 & Hw1).
  exists w. split.
  - left. assumption.
  - apply star_1; assumption.
Qed.

Lemma strongly_commute_commutes {A : Type} (R1 R2 : A -> A -> Prop) :
  strongly_commute R1 R2 -> commute R1 R2.
Proof.   intros H.
  assert (H1 : forall x y z, star R1 x y -> R2 x z -> exists w, reflc R2 y w /\ star R1 z w).
  - intros x y z Hxy; revert z. induction Hxy.
    + intros z Hxz. exists z. split; [left; assumption|constructor].
    + intros w Hw.
      destruct (H _ _ _ H0 Hw) as (t & [Hyt | <-] & Hwt).
      * destruct (IHHxy t Hyt) as (s & Hzs & Hts).
        exists s. split; [assumption|].
        eapply star_compose; eassumption.
      * exists z. split; [right; reflexivity|].
        eapply star_compose; eassumption.
  - intros x y z Hxy Hxz; revert y Hxy. induction Hxz; intros w Hxw.
    + exists w. split; [constructor|assumption].
    + destruct (H1 x w y Hxw H0) as (t & Hwt & Hyt).
      destruct (IHHxz t Hyt) as (s & Hts & Hzs).
      exists s. split; [|assumption].
      eapply star_compose; [|eassumption].
      apply reflc_star; assumption.
Qed.

Lemma commuting_diamond_commutes {A : Type} (R1 R2 : A -> A -> Prop) :
  commuting_diamond R1 R2 -> commute R1 R2.
Proof.   intros H. apply strongly_commute_commutes, commuting_diamond_strongly_commutes, H.
Qed.

Lemma diamond_is_confluent {A : Type} (R : A -> A -> Prop) :
  diamond R -> confluent R.
Proof.   apply commuting_diamond_commutes.
Qed.

Lemma between_star {A : Type} (R1 R2 : A -> A -> Prop) :
  (forall x y, R1 x y -> R2 x y) -> (forall x y, R2 x y -> star R1 x y) -> same_rel (star R1) (star R2).
Proof.   intros H1 H2 x y. split; intros H.
  - eapply star_impl; eassumption.
  - eapply star_star.
    eapply star_impl; eassumption.
Qed.

Definition weak_diamond {A : Type} (R : A -> A -> Prop) :=
  forall x y z, R x y -> R x z -> y = z \/ (exists w, R y w /\ R z w).

Lemma weak_diamond_diamond_reflc {A : Type} (R : A -> A -> Prop) :
  weak_diamond R -> diamond (reflc R).
Proof.   intros HD x y z [Hxy | <-] [Hxz | <-].
  - specialize (HD x y z Hxy Hxz).
    destruct HD as [-> | (w & Hyw & Hzw)].
    + exists z. split; right; reflexivity.
    + exists w. split; left; assumption.
  - exists y. split; [right; reflexivity|left; assumption].
  - exists z. split; [left; assumption|right; reflexivity].
  - exists x. split; right; reflexivity.
Qed.

Lemma weak_diamond_confluent {A : Type} (R : A -> A -> Prop) :
  weak_diamond R -> confluent R.
Proof.   intros H.
  apply weak_diamond_diamond_reflc, diamond_is_confluent in H.
  eapply diamond_ext; [|eassumption].
  apply star_reflc.
Qed.


Lemma commuting_confluent :
  forall {A : Type} (R1 R2 : A -> A -> Prop), confluent R1 -> confluent R2 -> commute R1 R2 -> confluent (union R1 R2).
Proof.   intros A R1 R2 Hcf1 Hcf2 Hcomm.
  assert (H : diamond (compose (star R1) (star R2))).
  - intros x1 z1 x3 (y1 & Hxy1 & Hyz1) (x2 & Hx12 & Hx23).
    destruct (Hcf1 _ _ _ Hxy1 Hx12) as (y2 & Hy12 & Hxy2).
    destruct (Hcomm _ _ _ Hy12 Hyz1) as (z2 & Hyz2 & Hz12).
    destruct (Hcomm _ _ _ Hxy2 Hx23) as (y3 & Hy23 & Hxy3).
    destruct (Hcf2 _ _ _ Hy23 Hyz2) as (z3 & Hyz3 & Hz23).
    exists z3.
    split; [exists z2|exists y3]; split; assumption.
  - apply diamond_is_confluent in H.
    eapply diamond_ext; [|exact H]. apply between_star.
    + intros x y [H1 | H2]; [exists y|exists x]; split; econstructor; try eassumption; constructor.
    + intros x z (y & Hxy & Hyz).
      eapply star_compose; eapply star_impl; try eassumption;
        intros u v Huv; [left|right]; assumption.
Qed.


Lemma convertible_confluent_common_reduce :
  forall (A : Type) (R : A -> A -> Prop),
    confluent R -> forall x y, convertible R x y -> exists z, star R x z /\ star R y z.
Proof.   intros A R Hconf x y Hconv. induction Hconv.
  - exists x. split; constructor.
  - destruct IHHconv as (w & Hyw & Hzw).
    destruct H as [Hxy | Hyx].
    + exists w. split; [|assumption]. econstructor; eassumption.
    + destruct (Hconf y x w) as (t & Hxt & Hwt).
      * apply star_1. assumption.
      * assumption.
      * exists t. split; [assumption|].
        eapply star_compose; eassumption.
Qed.


Rewriting one element of a list

Inductive step_one {A : Type} (R : A -> A -> Prop) : list A -> list A -> Prop :=
| step_one_step : forall x y L, R x y -> step_one R (x :: L) (y :: L)
| step_one_cons : forall x L1 L2, step_one R L1 L2 -> step_one R (x :: L1) (x :: L2).

Lemma step_one_decompose :
  forall (A : Type) (R : A -> A -> Prop) l1 l2, step_one R l1 l2 <-> exists l3 l4 x y, l1 = l3 ++ x :: l4 /\ l2 = l3 ++ y :: l4 /\ R x y.
Proof.   intros A R l1 l2. split; intros H.
  - induction H.
    + exists nil, L, x, y. tauto.
    + destruct IHstep_one as (l3 & l4 & a & b & H1); exists (x :: l3), l4, a, b.
      simpl; intuition congruence.
  - destruct H as (l3 & l4 & x & y & -> & -> & H).
    induction l3; simpl; constructor; assumption.
Qed.

Lemma step_one_star :
  forall (A : Type) (R : A -> A -> Prop), same_rel (star (step_one R)) (Forall2 (star R)).
Proof.   intros A R x y. split; intros H.
  - induction H.
    + apply Forall2_map_same, Forall_True. intros; apply star_refl.
    + enough (Forall2 (star R) x y).
      * apply Forall2_comm in H1.
        eapply Forall3_select23, Forall3_impl; [|eapply Forall3_from_Forall2; eassumption].
        intros ? ? ? [? ?]; eapply star_compose; simpl in *; eassumption.
      * clear H0 IHstar. induction H; constructor.
        -- apply star_1; assumption.
        -- apply Forall2_map_same, Forall_True. intros; apply star_refl.
        -- apply star_refl.
        -- assumption.
  - induction H.
    + apply star_refl.
    + eapply star_compose; [|eapply star_map_impl with (f := fun l => y :: l); [|eassumption]; intros; constructor; assumption].
      eapply star_map_impl with (f := fun x => x :: l); [|eassumption].
      intros; constructor; assumption.
Qed.

Lemma step_one_impl_transparent :
  forall (A : Type) (R1 R2 : A -> A -> Prop) L1 L2, (forall x y, R1 x y -> R2 x y) -> step_one R1 L1 L2 -> step_one R2 L1 L2.
Proof.   intros A R1 R2 L1 L2 H1 H2; induction H2; constructor; [|assumption].
  apply H1, H.
Defined.

Lemma step_one_impl_strong_transparent :
  forall (A : Type) (R1 R2 : A -> A -> Prop) L1 L2, (forall x y, R1 x y -> R2 x y) -> step_one R1 L1 L2 -> step_one (fun x y => R1 x y /\ R2 x y) L1 L2.
Proof.   intros A R1 R2 L1 L2 H1 H2. eapply step_one_impl_transparent; [|eassumption].
  intros; split; [assumption|apply H1; assumption].
Defined.


Lemma star_list :
  forall (A B : Type) (RA : A -> A -> Prop) (RB : B -> B -> Prop) (f : list A -> B) l1 l2,
    (forall l1 l2 x y, RA x y -> RB (f (l1 ++ x :: l2)) (f (l1 ++ y :: l2))) -> Forall2 (star RA) l1 l2 -> star RB (f l1) (f l2).
Proof.   intros A B RA RB f l1 l2 Himpl Hl.
  enough (H : forall l, star RB (f (l ++ l1)) (f (l ++ l2))); [exact (H nil)|].
  induction Hl as [|x y l1 l2 Hxy Hl IH].
  - intros. constructor.
  - intros l. eapply star_compose.
    + specialize (IH (l ++ x :: nil)). rewrite <- !app_assoc in IH. apply IH.
    + eapply star_map_impl with (f := fun t => f (l ++ t :: l2)); [|eassumption].
      intros; apply Himpl; assumption.
Qed.


Lemma Acc_star_down :
  forall (A : Type) (R : A -> A -> Prop) x y, Acc R x -> star R y x -> Acc R y.
Proof.   intros A R x y H1 H2. induction H2.
  - assumption.
  - apply IHstar in H1. inversion H1.
    apply H0. assumption.
Qed.


Lemma Acc_plus :
  forall (A : Type) (R : A -> A -> Prop) x, Acc R x -> Acc (plus R) x.
Proof.   intros A R x H. induction H.
  constructor. intros y Hy.
  apply flip_plus_iff in Hy.
  inversion Hy; subst.
  - apply H0. assumption.
  - eapply Acc_star_down; [eapply H0; eassumption|].
    apply star_1, flip_plus_iff; eassumption.
Qed.


Definition updatep {A B : Type} (f : A -> B -> Prop) (x : A) (P : B -> Prop) (u : A) (v : B) :=
  (u <> x /\ f u v) \/ (u = x /\ P v).

Inductive AccI {A : Type} (B : A -> Prop) (R : A -> A -> Prop) : A -> Prop :=
| AccI_base : forall a, B a -> AccI B R a
| AccI_intro : forall a, (forall b, R b a -> AccI B R b) -> AccI B R a.

Lemma updatep_wf2 :
  forall (A : Type) (R : A -> A -> Prop) u (P : A -> Prop),
    (forall v, P v -> AccI (fun v => plus R u v) (flip (updatep R u P)) v) -> well_founded (flip R) -> well_founded (flip (updatep R u P)).
Proof.   intros A R u P H Hwf v.
  induction (Acc_plus _ _ _ (Hwf v)). constructor.
  intros v [[Huv HR] | [-> HP]].
  - apply H1, plus_1, HR.
  - specialize (H _ HP). clear HP. induction H.
    + apply H1, flip_plus_iff, H.
    + constructor. apply H2.
Qed.

Lemma updatep_wf_none :
  forall (A : Type) (R : A -> A -> Prop) u (P : A -> Prop),
    ~ P u -> (forall v, ~ R v u) -> well_founded (flip R) -> well_founded (flip (updatep R u P)).
Proof.   intros A R u P HP Hu Hwf.
  assert (Hwf1 : forall v, v <> u -> Acc (flip (updatep R u P)) v).
  - intros v Hv. induction (Hwf v). constructor.
    intros v [[Huv HR] | [-> HPv]].
    + apply H0; [assumption|]. intros ->; eapply Hu, HR.
    + tauto.
  - intros v. constructor; intros w [[Hvw HR2] | [-> HPw]].
    + apply Hwf1. intros ->; eapply Hu, HR2.
    + apply Hwf1. intros ->; apply HP, HPw.
Qed.

Lemma Acc_ext :
  forall (A : Type) (R1 R2 : A -> A -> Prop) x, (forall u v, R2 u v -> R1 u v) -> Acc R1 x -> Acc R2 x.
Proof.   intros A R1 R2 x H Hwf; induction Hwf; constructor.
  intros y HR; apply H1, H, HR.
Qed.

Lemma AccI_ext :
  forall (A : Type) (B : A -> Prop) (R1 R2 : A -> A -> Prop) x, (forall u v, R2 u v -> R1 u v) -> AccI B R1 x -> AccI B R2 x.
Proof.   intros A B R1 R2 x H Hwf; induction Hwf.
  - apply AccI_base; assumption.
  - apply AccI_intro; intros; apply H1, H, H2.
Qed.

Lemma well_founded_ext :
  forall (A : Type) (R1 R2 : A -> A -> Prop), (forall u v, R2 u v -> R1 u v) -> well_founded R1 -> well_founded R2.
Proof.   intros A R1 R2 H Hwf x; eapply Acc_ext; [eassumption|apply Hwf].
Qed.

Lemma Acc_cycle :
  forall (A : Type) (R : A -> A -> Prop) x, plus R x x -> Acc (flip R) x -> False.
Proof.   intros A R x Hplus Hacc. induction Hacc.
  inversion Hplus; subst.
  - eapply H0; eassumption.
  - eapply H0; [eassumption|].
    eapply plus_compose_star_right; [eassumption|].
    apply star_1; assumption.
Qed.