Library CFG.Separate

Require Export Inlining.

Definition charfree u := s, s u A, s = Vs A.
Definition uniform G := A u, R A u G a, Ts a u u = [Ts a].

Instance dec_charfree u : dec (charfree u).
Proof.
  unfold charfree.
  induction u as [| [a | A] u IHu].
  - left. intros s H. destruct H.
  - right. intros H.
    assert ( : Ts a (Ts a :: u)) by auto.
    destruct (H (Ts a) ) as [A H']. inv H'.
  - destruct IHu as [IH | IH].
    + left. intros s [H | H] ; [ A |] ; auto.
    + right. intros H. apply IH.
      intros s . apply H. auto.
Defined.


Lemma pickChar u :
  ¬ charfree u { a | Ts a u}.
Proof.
  intros H.
  induction u as [| [a | A] u IHu].
  - exfalso. apply H. intros s . destruct .
  - a. auto.
  - assert ( : ¬ charfree u). {
      intros . apply H.
      intros s . destruct as [ | ] ; [ A| ] ; auto. }
    destruct (IHu ) as [a ]. a. auto.
Qed.


Lemma pickCharRule G :
  { a | A u, R A u G (Ts a) u |u| 2} + uniform G.
Proof.
  induction G as [| [A u] Gr IHGr].
  - right. intros A u [].
  - destruct IHGr as [[a IH] | IH].
    + left. a. destruct IH as [A' [u' [ [ ]]]].
       A', u'. repeat split ; auto.
    + decide (charfree u) as [D | D].
      × right. intros A' u' [ | ] a ; eauto.
        inv . destruct (D (Ts a) ) as [b T]. inv T.
      × { apply pickChar in D. destruct D as [a D].
          destruct u as [| [b | B] [| s u]].
          - exfalso. destruct D as [].
          - right. intros A' u' [ | ] c ; eauto.
            inv . destruct as [ | ] ; now inv .
          - left. a, A, (Ts b :: s :: u). repeat split ; simpl ; auto ; omega.
          - exfalso. destruct D as [D | D] ; inv D.
          - left. a, A, (Vs B :: s :: u). repeat split ; simpl ; auto ; omega. }
Qed.


Definition step (G : grammar) : grammar.
  destruct (pickCharRule G) as [[a H] | H ].
  - destruct (pickFresh G) as [B N].
    exact (R B [Ts a] :: substG G (Ts a) [Vs B]).
  - exact G.
Defined.

Fixpoint count_chars u :=
  match u with
    [] ⇒ 0
  | Vs A :: urcount_chars ur
  | Ts t :: urS (count_chars ur)
  end.

Fixpoint count_sep G :=
  match G with
    [] ⇒ 0
  | R A u :: Grif decision (|u| < 2) then count_sep Gr
                  else count_chars u + count_sep Gr
  end.

Definition sep G := it step (count_sep G) G.

Separation yields uniform grammar


Lemma count_sep_split G G' :
  count_sep (G G') = count_sep G + count_sep G'.
Proof.
  induction G as [| [A u] Gr IHGr] ; simpl ; try decide (| u | < 2) ; auto.
  rewrite plus_assoc. now f_equal.
Qed.


Lemma count_chars_substL u a B :
  count_chars u count_chars (substL u (Ts a) [Vs B]).
Proof.
  induction u as [| [b | A] u] ; simpl ; auto.
  decide (Ts b = Ts a) ; simpl ; omega.
Qed.


Lemma count_sep_substL G a B :
  count_sep G count_sep (substG G (Ts a) [Vs B]).
Proof.
  induction G as [| [A u] Gr IHGr] ; simpl ; auto.
  decide (| u | < 2) as [D | D] ; rewrite substL_length_unit with (x := Ts a) (x' := Vs B) (D := symbol_eq_dec) in D ;
    decide (| substL u (Ts a) [Vs B] | < 2) ; try tauto.
  cut (count_chars u count_chars (substL u (Ts a) [Vs B])) ; try omega.
  apply count_chars_substL.
Qed.


Lemma count_chars_split :
  count_chars ( ) = count_chars + count_chars .
Proof.
  induction as [| [a | A] ] ; simpl ; auto.
Qed.


Lemma count_chars_decr B u a :
  Ts a u count_chars u > count_chars (substL u (Ts a) [Vs B]).
Proof.
  intros .
  apply in_split in .
  destruct as [ [ ]]. rewrite .
  replace ( Ts a :: ) with ( [Ts a] ) by auto.
  repeat rewrite substL_split.
  repeat rewrite count_chars_split.
  repeat rewrite plus_assoc.
  cut (count_chars [Ts a] > count_chars (substL [Ts a] (Ts a) [Vs B])).
  - intros .
    pose (count_chars_substL a B).
    pose (count_chars_substL a B). omega.
  - simpl. decide (Ts a = Ts a) ; try tauto. auto.
Qed.


Lemma count_sep_decr G A B u a :
  R A u G Ts a u |u| 2 count_sep G > count_sep (substG G (Ts a) [Vs B]).
Proof.
  intros H U T.
  apply in_split in H.
  destruct H as [ [ H]]. rewrite H.
  replace ( R A u :: ) with ( [R A u] ) by auto.
  do 2 rewrite substG_split.
  repeat rewrite count_sep_split.
  repeat rewrite plus_assoc.
  cut (count_sep [R A u] > count_sep (substG [R A u] (Ts a) [Vs B])).
  - intros C. pose ( := count_sep_substL a B).
    pose ( := count_sep_substL a B). omega.
  - simpl. decide (| u | < 2) as [D | D] ; try omega.
    rewrite substL_length_unit with (x := Ts a) (x' := Vs B) (D := symbol_eq_dec) in D.
    decide (| substL u (Ts a) [Vs B] | < 2) ; try tauto.
    do 2 rewrite plus_n_O.
    now apply count_chars_decr.
Qed.


Lemma count_decr G :
  step G G count_sep G > count_sep (step G).
Proof.
  intros St.
  unfold step in ×.
  destruct (pickCharRule G) as [[a [B [v [ [ ]]]]] | H ] ; try tauto.
  destruct (pickFresh G) as [C N].
  simpl. eapply count_sep_decr ; eauto.
Qed.


Lemma fp_sep G :
  FP step (sep G).
Proof.
  apply it_fp. intros n.
  decide (step (it step n G) = (it step n G)).
  - left. auto.
  - right. simpl. now apply count_decr in .
Qed.


Lemma fp_uniform G :
  FP step G uniform G.
Proof.
  intros Ss.
  unfold step, FP in Ss.
  destruct (pickCharRule G) as [[a [B [v [ [ ]]]]] | H ].
  - destruct (pickFresh G) as [C N].
    destruct G ; inversion Ss.
    exfalso. assert ( : Vs C symbs (r :: G)) by (rewrite Ss ; simpl ; auto).
    specialize (N (Vs C) ). unfold sless' in N. destruct B as [i] ; omega.
  - intros A' u' Ru'. specialize (H A' u' Ru') ; auto.
Qed.


Lemma sep_uniform G :
  uniform (sep G).
Proof.
  apply fp_uniform, fp_sep.
Qed.


Separation preserves languages


Lemma substG_der_equiv G A u B s :
  fresh G (Vs B) A B s Vs B terminal u (der (R B [s] :: (substG G s [Vs B])) A u der G A u).
Proof.
  intros N Do U T.
  split ; intros D.
  - rewrite substG_undo with (G := G) (B := B) (s := s) ; auto.
    apply der_G_substG ; auto ; intros H.
    + rewrite substG_dom in H. apply symbs_dom in H.
      apply fresh_symbs in N. tauto.
    + destruct H ; tauto.
    + destruct (T (Vs B) H) as [t T']. inv T'.
  - rewrite substG_undo with (G := G) (B := B) (s := s) in D ; auto.
    now apply der_substG_G.
Qed.


Lemma step_der_equiv G A u :
  Vs A dom G terminal u (der (step G) A u der G A u).
Proof.
  intros Do T.
  unfold step.
  destruct (pickCharRule G) as [[a [B [v [ [ ]]]]] | H ] ; [| firstorder].
  destruct (pickFresh G) as [C N].
  apply substG_der_equiv ; auto.
  - intros H. inv H. apply symbs_dom in Do.
    specialize (N (Vs C) Do). unfold sless' in N. omega.
  - intros . inv .
Qed.


Lemma step_dom G :
  dom G dom (step G).
Proof.
  unfold step.
  destruct (pickCharRule G) as [[a [B [v [ [ ]]]]] | H ] ; auto.
  destruct (pickFresh G) as [C N].
  simpl. rewrite substG_dom. auto.
Qed.


Lemma sep_der_equiv G A u :
  Vs A dom G terminal u (der (sep G) A u der G A u).
Proof.
  unfold sep. remember (count_sep G) as n. clear Heqn.
  revert G.
  induction n ; intros G D T ; simpl ; try tauto.
  rewrite step_der_equiv ; auto.
  apply it_ind ; auto.
  intros G' . now apply step_dom.
Qed.


Lemma sep_language G A u :
  Vs A dom G (language G A u language (sep G) A u).
Proof.
  intros D.
  split ; intros [ ] ; split ; try eapply sep_der_equiv ; eauto.
Qed.