regexp.concrete.automata.concat


Section Cxt.
  Context {B : sort}{St0 St1 : sort}.

  Context (mac0 : NFA B St0) (mac1 : NFA B St1).

  Definition State : sort := (St0 St1).

  Definition start0 : subset.t St0 := start mac0.
  Definition start1 : subset.t St1 := start mac1.

  Definition final0 : subset.t St0 := final mac0.
  Definition final1 : subset.t St1 := final mac1.

  Definition hasfinal0 (U : subset.t St0) := subset.inhabited (intersection U final0).

  Lemma hasfinal0_denote (U : subset.t St0) : hasfinal0 U = abstract.automata.concat.hasfinal0 (automata.denote mac0) (subset.denote U).
    rewrite /hasfinal0 /concat.hasfinal0.
    apply/subset.inhabitedP/existsP; by casex; rewrite subset.intersection_spec; x.
  Qed.

  Definition crossing (U : subset.t St0) : subset.t St1 := if hasfinal0 U then start1 else subset.empty.
  Definition crossRel : relation.binary.t St0 relation.t St0 St1 := function.map crossing.

  Definition rel01 : B ~> relation.t St0 St1 := function.map crossRel (trans mac0).

  Definition mkTrans : transition.t B State :=
    function.zipWith4 relation.matrix (trans mac0) rel01 (function.constant relation.empty) (trans mac1).

  Definition initial : subset.t State := if hasfinal0 start0 then start0 start1 else start0 .
  Definition terminal : subset.t State := final1.

  Definition build := {|
                       trans := mkTrans;
                       start := initial;
                       final := terminal
                     |}.

  Lemma equality : automata.denote build = (abstract.automata.concat.build (automata.denote mac0) (automata.denote mac1)).
  Proof using Type.
    apply abstract.automata.eq_equiv.
    rewrite /build /initial /terminal /mkTrans /automata.equiv //= /concat.initial /concat.terminal /concat.mkTrans.
    intuition; apply /eqP.
    - rewrite hasfinal0_denote.
      set u := concat.hasfinal0 _ _.
      by case: u; rewrite ?injDU ?union_spec ?injl_spec ?injr_spec ?empty_spec ?imset0 ?setU0 //=; intuition.
    - by rewrite ?injDU ?union_spec ?injl_spec ?injr_spec ?empty_spec ?imset0 ?set0U //=; intuition.
    - rewrite -ffunP /utmatrixx.
      rewrite ffunE function.to_map zip_pointwise4 ffunE matrix_spec; apply abstract.relation.matrix_eq.
      rewrite /concat.tr0 /concat.tr1 constantE /transition.denote ?ffunE ?function.to_map ?relation.empty_spec -?ffunP; intuition.

      rewrite ?ffunE /crossRel ?function.to_map /crossing /concat.prefinal0 hasfinal0_denote /abstract.automata.trans //=.
      do 2 rewrite /transition.denote function.denoteE function.to_map /relation.denote.
      set cond := concat.hasfinal0 _ _; by case: cond; rewrite ?subset.empty_spec.
  Qed.

  Theorem correctness : (accept build accept mac0 ++ accept mac1)%lan.
  Proof using Type.
    by rewrite /accept equality abstract.automata.concat.correctness.
  Qed.
End Cxt.