let union (a : nfa)
          (b : nfa) : nfa =
  let offset = a.next_q in
  let convert x = x + offset in
  let q = copy a.q in
  let _ = iter (fun m2q -> add q (convert m2q)) b.q in
  let delta = Hashtbl.create (Hashtbl.length a.delta + Hashtbl.length b.delta) in
  let _ = copy_table a.delta delta (fun x -> x) in
  let _ = copy_table b.delta delta convert in
  let epsilon = Hashtbl.create (Hashtbl.length a.delta + Hashtbl.length b.delta) in
  let _ = copy_table a.epsilon epsilon (fun x -> x) in
  let _ = copy_table b.epsilon epsilon convert in
  let result = { s = 0; f = 0; delta = delta; epsilon = epsilon; q = q;
                 next_q = a.next_q + b.next_q } in
  let newstart = new_state result in
  let newfinal = new_state result in
    add_trans result newstart Epsilon a.s;
    add_trans result newstart Epsilon (convert b.s);
    add_trans result a.f Epsilon newfinal;
    add_trans result (convert b.f) Epsilon newfinal;
    result.s <- newstart;
    result.f <- newfinal;
    result