Library CFG.Separate

Require Export Inlining.

Definition charfree u := s, s el u A, s = Vs A.
Definition uniform G := A u, R A u el G a, Ts a el 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 (H0 : Ts a el (Ts a :: u)) by auto.
    destruct (H (Ts a) H0) as [A H']. inv H'.
  - destruct IHu as [IH | IH].
    + left. intros s [H | H] ; [ A |] ; auto.
    + right. intros H. apply IH.
      intros s H0. apply H. auto.
Defined.

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

Lemma pickCharRule G :
  { a | A u, R A u el G (Ts a) el 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' [H0 [H1 H2]]]].
       A', u'. repeat split ; auto.
    + decide (charfree u) as [D | D].
      × right. intros A' u' [H0 | H0] a H1 ; eauto.
        inv H0. destruct (D (Ts a) H1) 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' [H0 | H0] c H1 ; eauto.
            inv H0. destruct H1 as [H1 | H1] ; now inv H1.
          - 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 u1 u2 :
  count_chars (u1 ++ u2) = count_chars u1 + count_chars u2.
Proof.
  induction u1 as [| [a | A] u1] ; simpl ; auto.
Qed.

Lemma count_chars_decr B u a :
  Ts a el u count_chars u > count_chars (substL u (Ts a) [Vs B]).
Proof.
  intros H0.
  apply in_split in H0.
  destruct H0 as [u1 [u2 H0]]. rewrite H0.
  replace (u1 ++ Ts a :: u2) with (u1 ++ [Ts a] ++ u2) 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 H2.
    pose (count_chars_substL u1 a B).
    pose (count_chars_substL u2 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 el G Ts a el 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 [G1 [G2 H]]. rewrite H.
  replace (G1 ++ R A u :: G2) with (G1 ++ [R A u] ++ G2) 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 (C0 := count_sep_substL G1 a B).
    pose (C1 := count_sep_substL G2 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 [H0 [H1 H2]]]]] | 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 n0.
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 [H0 [H1 H2]]]]] | H ].
  - destruct (pickFresh G) as [C N].
    destruct G ; inversion Ss.
    exfalso. assert (H5 : Vs C el symbs (r :: G)) by (rewrite <- Ss ; simpl ; auto).
    specialize (N (Vs C) H5). 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 el 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 [H0 [H1 H2]]]]] | 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 H5. inv H5.
Qed.

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

Lemma sep_der_equiv G A u :
  Vs A el 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' H0. now apply step_dom.
Qed.

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