Definition set_queue {W O} (l : list input) :=
    modify (W := W)(O := O) (fun d => Build_PB_data l (state d)).Definition set_state {W O} (st : data) :=
    modify (W := W)(O := O) (fun d => Build_PB_data (queue d) st).Ltac pb_unfold := unfold set_queue, set_state in *; monad_unfold.Instance PB_base_params : BaseParams :=
    Build_BaseParams
      PB_data
      PB_input
      PB_output.Instance PB_multi_params : MultiParams PB_base_params :=
    Build_MultiParams
      PB_base_params
      msg_eq_dec
      name_eq_dec
      all_nodes_all
      NoDup_all_nodes
      PB_init
      PB_net
      PB_input_handler.Definition inputs_1 (tr : list ((@input base_params) * (@output base_params))) :
      list (@input base_params) :=
    map (@fst _ _) tr.Definition inputs_m (tr : list (name * (@input PB_base_params + list (@output PB_base_params)))) :
    list (@input base_params) :=
    filterMap (fun x => match x with
                          | (Primary, inl (Request i)) => Some i
                          | _ => None
                        end)
              tr.Definition outputs_1 (tr : list ((@input base_params) * (@output base_params))) :
    list (@output base_params) :=
    map (@snd _ _) tr.Definition correspond (st : @data base_params) (sigma : name -> @data PB_base_params) tr_1 tr_m :=
    let (d, os) := processInputs (state (sigma Primary)) (queue (sigma Primary)) in
    outputs_m tr_m ++ os = outputs_1 tr_1 /\
    d = st.

(* Specifications: *)
Lemma inputs_m_app : forall l1 l2, inputs_m (l1 ++ l2) = inputs_m l1 ++ inputs_m l2.
Lemma inputs_m_inr : forall h t tr, inputs_m ((h, inr t) :: tr) = inputs_m tr.
Lemma outputs_m_app : forall tr1 tr2, outputs_m (tr1 ++ tr2) = outputs_m tr1 ++ outputs_m tr2.
Lemma inputs_m_primary_inl : forall i l, inputs_m ((Primary, inl (Request i)) :: l) = i :: inputs_m l.
Lemma inputs_m_inl_read : forall h l, inputs_m ((h, inl Read) :: l) = inputs_m l.
Lemma inputs_1_app : forall tr1 tr2, inputs_1 (tr1 ++ tr2) = inputs_1 tr1 ++ inputs_1 tr2.
Lemma outputs_1_app : forall tr1 tr2, outputs_1 (tr1 ++ tr2) = outputs_1 tr1 ++ outputs_1 tr2.
Lemma processInputs_app : forall l1 l2 d, processInputs d (l1 ++ l2) = let (d', os) := processInputs d l1 in let (d'', os') := processInputs d' l2 in (d'', os ++ os').
Lemma inputs_m_backup : forall i l, inputs_m ((Backup, inl i) :: l) = inputs_m l.
Lemma inputs_1_nil_is_nil : forall tr, inputs_1 tr = nil -> tr = nil.
Lemma processInputs_cons_defn : forall (st : @data base_params) (x : @input base_params) l, processInputs st (x :: l) = let (os, d') := handler x st in let (d'', os') := processInputs d' l in (d'', os :: os').
Lemma correspond_reachable : forall net tr_m, step_async_star step_async_init net tr_m -> forall st tr_1, step_1_star init st tr_1 -> inputs_1 tr_1 = inputs_m tr_m -> correspond st (nwState net) tr_1 tr_m.
Lemma correspond_inductive : forall net net' tr_m', step_async net net' tr_m' -> forall st st' tr_m tr_1 tr_1', correspond st (nwState net) tr_1 tr_m -> step_1_star st st' tr_1' -> inputs_1 tr_1' = inputs_m tr_m' -> correspond st' (nwState net') (tr_1 ++ tr_1') (tr_m ++ tr_m').