Library DistributeFix

Require Export Omega Coq.Setoids.Setoid List Util AutoIndTac Base Congruence FreeVariables.

Set Implicit Arguments.
Unset Printing Records.

Require Import Autosubst.

Unfolding properties of decomposed recursions


Fact decomposed_subst s t u
  : bound 0 1 s
    → bound 0 1 t
    → (part s t).[u /] =T CFPChoice s.[ren(shift)] (CFPSeq t.[ren(shift)] u).
Proof.
  intros. split; intros.
  - asimpl in H1. inv H1; eauto using TC.
     + constructor.
       rewrite bound_subst with (n:= 0) (k:= 1) (f:= shift) in H5; eauto using simulatesI_shift.
     + constructor 7. inv H5; eauto using TC.
       constructor; eauto.
       rewrite bound_subst with (n:= 0) (k:= 1) (f:= shift) in H4; eauto using simulatesI_shift.
  - inv H1; eauto using TC.
    + asimpl. constructor.
      rewrite bound_subst with (n:= 0) (k:= 1) (f:= shift); eauto using simulatesI_shift.
    + asimpl. constructor 7. inv H5; eauto using TC.
      constructor; eauto.
      rewrite bound_subst with (n:= 0) (k:= 1) (f:= shift); eauto using simulatesI_shift.
Qed.

Fact decomposed_unfold s t n
  : bound 0 1 s
    → bound 0 1 t
    → unfold (part s t) (S n)
       =T CFPChoice (s.[ren(shift)]) (CFPSeq t.[ren(shift)] (unfold (part s t) n)).
Proof.
  intros.
  change ( (part s t).[unfold (part s t) n /] =T
                                                 CFPChoice s.[ren shift] (CFPSeq t.[ren shift] (unfold (part s t) n))).
  apply decomposed_subst; eauto.
Qed.

Distributivity of decomposed recursions


Lemma decomposed_unfold_distribute s t u n
  : bound 0 1 s
    → bound 0 1 t
    → bound 0 1 u
    → (unfold (part (CFPSeq s u) t) n)
       =T CFPSeq (unfold (part s t) n) u.[ren(shift)].
Proof.
  intros. general induction n.
  - symmetry. asimpl. apply Seq_Null_absorb_left.
  - rewrite decomposed_unfold; eauto.
    + rewrite IHn; eauto.
      assert ((CFPSeq s u).[ren shift] =T CFPSeq s.[ren(shift)] u.[ren(shift)]).
      { asimpl. reflexivity. }
      rewrite H2.
      rewrite <- Seq_assoc.
      rewrite <- Seq_Choice_distribute2.
      rewrite <- decomposed_unfold; eauto. reflexivity.
    + constructor; eauto.
Qed.

Lemma decomposed_unfold_distribute_lift s t u n
  : bound 0 1 s
    → bound 0 1 t
    → (unfold (part (CFPSeq s u.[ren(+1)]) t) n)
       =T CFPSeq (unfold (part s t) n) u.
Proof.
  intros. rewrite decomposed_unfold_distribute; eauto.
  - asimpl. rewrite shift_id. asimpl. reflexivity.
  - apply bound_ren. intros. left. simpl. omega.
Qed.

Lemma decompose_Fix_distribute s t u
  : bound 0 1 s
    → bound 0 1 t
    → bound 0 1 u
    → (CFPFix (part (CFPSeq s u) t))
       =T (CFPSeq (CFPFix (part s t)) u.[ren(shift)]).
Proof.
  intros. split; intros.
  - apply Fix_unfold_subsume in H2. destruct H2 as [n H2].
    apply decomposed_unfold_distribute in H2; eauto.
    inv H2; eauto using TC.
    constructor; eauto. apply unfold_Fix_subsume with (n:= n).
    eauto.
  - inv H2; eauto using TC. apply Fix_unfold_subsume in H5.
    destruct H5 as [n H5]. apply unfold_Fix_subsume with (n:= n).
    apply decomposed_unfold_distribute; eauto. constructor; eauto.
Qed.

Lemma decomposed_Fix_distribute_lift s t u
  : bound 0 1 s
    → bound 0 1 t
    → (CFPFix (part (CFPSeq s u.[ren(+1)]) t))
       =T (CFPSeq (CFPFix (part s t)) u).
Proof.
  intros. rewrite decompose_Fix_distribute; eauto.
  - assert (u.[ren ((+1) >>> shift)] = u.[ids]).
    { apply extens. intros. destruct n; eauto. }
    asimpl. rewrite H1. asimpl. reflexivity.
  - apply bound_ren. left. simpl. omega.
Qed.

Transformation from decomposed recursions to iterations


Lemma decomposed_Star s t
  : bound 0 1 s
     → bound 0 1 t
     → CFPFix (part s t)
        =T CFPSeq (Star t) s.[ren(shift)].
Proof.
  intros.
  unfold Star.
  rewrite <- decompose_Fix_distribute; eauto using bound.
  unfold part. rewrite Seq_Eps_iden_left.
  reflexivity.
Qed.

Lemma decomposed_Star_lift s t
  : bound 0 1 s
     → bound 0 1 t
     → CFPFix (part s.[ren(+1)] t)
        =T CFPSeq (Star t) s.
Proof.
  intros.
  unfold Star.
  rewrite <- decomposed_Fix_distribute_lift; eauto using bound.
  unfold part. rewrite Seq_Eps_iden_left. reflexivity.
Qed.