Inductive begin_end_state {state: Type}: state -> trace state -> MetaState state -> Prop :=
| begin_end_empty: forall s, begin_end_state s empty_stream (Terminating s)
| begin_end_fin: forall s ms s' ms' tr n,
    is_n_stream (S n) tr ->
    tr 0 = Some (s, ms) ->
    tr n = Some (s', ms') ->
    begin_end_state s tr ms'
| begin_end_inf: forall s ms tr,
    is_inf_stream tr ->
    tr 0 = Some (s, ms) ->
    begin_end_state s tr NonTerminating.Inductive begin_end_state {state: Type}: state -> trace state -> MetaState state -> Prop :=
| begin_end_empty: forall s, begin_end_state s empty_stream (Terminating s)
| begin_end_fin: forall s ms s' ms' tr n,
    is_n_stream (S n) tr ->
    tr 0 = Some (s, ms) ->
    tr n = Some (s', ms') ->
    begin_end_state s tr ms'
| begin_end_inf: forall s ms tr,
    is_inf_stream tr ->
    tr 0 = Some (s, ms) ->
    begin_end_state s tr NonTerminating.Inductive begin_end_state {state: Type}: state -> trace state -> MetaState state -> Prop :=
| begin_end_empty: forall s, begin_end_state s empty_stream (Terminating s)
| begin_end_fin: forall s ms s' ms' tr n,
    is_n_stream (S n) tr ->
    tr 0 = Some (s, ms) ->
    tr n = Some (s', ms') ->
    begin_end_state s tr ms'
| begin_end_inf: forall s ms tr,
    is_inf_stream tr ->
    tr 0 = Some (s, ms) ->
    begin_end_state s tr NonTerminating.Inductive begin_end_state {state: Type}: state -> trace state -> MetaState state -> Prop :=
| begin_end_empty: forall s, begin_end_state s empty_stream (Terminating s)
| begin_end_fin: forall s ms s' ms' tr n,
    is_n_stream (S n) tr ->
    tr 0 = Some (s, ms) ->
    tr n = Some (s', ms') ->
    begin_end_state s tr ms'
| begin_end_inf: forall s ms tr,
    is_inf_stream tr ->
    tr 0 = Some (s, ms) ->
    begin_end_state s tr NonTerminating.Definition begin_state {state: Type} (tr: trace state) (s: state): Prop :=
  exists ms, begin_end_state s tr ms.Definition end_state {state: Type} (tr: trace state) (ms: MetaState state): Prop :=
  exists s, begin_end_state s tr ms.Definition ctrace2trace
           {cmd: Type}
           {state: Type}: trace (cmd * state) -> trace state := 
  stream_map (fun p => match p with ((c, s), mcs) => (s, lift_function snd mcs) end).

Lemma begin_end_state_singleton_trace_rev: forall {state: Type} (s s': state) ms ms', begin_end_state s' (singleton_trace s ms) ms' -> s = s' /\ ms = ms'.