Section Product_automaton.
Variable op: Prop -> Prop -> Prop.
Variable op_dec: forall P Q, dec P -> dec Q -> dec (op P Q).
Definition prod_delta: A (x) A' -> Sig -> A (x) A' :=
fun P x  => match P with (q1,q2) => (delta_S q1 x, delta_S q2 x) end.
Definition prod_pred := (fun P => match P with (q1,q2) => op (@F A q1) (@F A' q2) end).
Global Instance prod_pred_dec P: dec (prod_pred P).
Definition prod_F  := DecPred prod_pred.
Definition prod := DFA (s,s) prod_F prod_delta.
End Product_automaton.
Arguments prod op {op_dec}.
Definition intersect := prod and.
Definition U :=  prod or.
Definition diff := prod (fun P Q => P /\ ~ Q).
Definition lang_incl := forall w, in_lang A w -> in_lang A' w.
End Operations.
Definition lang_equiv A A':= lang_incl A A' /\ lang_incl A' A.
Instance lang_sub_dec A A' : dec (lang_incl A A').
Instance equiv_eq_dec A A': dec (lang_equiv A A').
(** * Nondeterministic finite automata (NFA)*)
Record nfa := NFA {
Q :> finType;
q0:Q;
Q_acc: decPred Q;
delta_Q: Q -> Sig -> decPred Q
}.
Implicit Type B : nfa.
Implicit Type A: dfa.
Fixpoint delta_Q_star B q w: B -> Prop  :=
match w with
| nil => fun q' => q' = q
|x::w' => fun q'' => exists q', delta_Q q x q' /\ delta_Q_star q' w' q''
end.
Arguments delta_Q_star {B} q w q'.
Instance delta_Q_star_dec B (q q': B) w: dec (delta_Q_star q w q').

Lemma delta_Q_star_trans B w w' (q q' q'': B) : delta_Q_star q w q' /\ delta_Q_star q' w' q'' -> delta_Q_star q (w ++ w') q''.