Definition good_op_move (x y : op) : Prop :=
    (forall k k', ~ (x = O k /\ y = I k')) /\
    (forall k, ~ (x = I k /\ y = O k)).

(* Specifications: *)
Lemma op_equiv_Permutation : forall xs ys, op_equivalent xs ys -> Permutation xs ys.
Lemma op_equiv_ack_op_lr : forall xs ys, op_equivalent xs ys -> forall k, acknowledged_op k xs -> acknowledged_op k ys.
Lemma op_equiv_ack_op_rl : forall xs ys, op_equivalent xs ys -> forall k, acknowledged_op k ys -> acknowledged_op k xs.
Lemma acknowledged_op_defn : forall k xs, acknowledged_op k xs -> In (O k) xs.
Lemma good_move_U_l : forall k x, good_move (IRU k) x.
Lemma good_move_IU_neq : forall k k', k <> k' -> good_move (IRI k) (IRU k').
Lemma good_move_IO_neq : forall k k', k <> k' -> good_move (IRI k) (IRO k').
Lemma not_good_op_move_IO : forall k, good_op_move (I k) (O k) -> False.
Lemma not_good_op_move_OI : forall k k', good_op_move (O k) (I k') -> False.
Lemma good_op_move_good_move_IO : forall k k', good_op_move (I k) (O k') -> good_move (IRI k) (IRO k').
Lemma good_op_move_cases : forall x y, good_op_move x y -> exists k k', (x = I k /\ y = I k') \/ (x = O k /\ y = O k') \/ (k <> k' /\ x = I k /\ y = O k').
Lemma acknowledged_op_I_cons_reduce : forall k k' l, acknowledged_op k (I k' :: l) -> acknowledged_op k l.
Lemma acknowledged_op_I_cons_expand : forall k k' l, acknowledged_op k l -> acknowledged_op k (I k' :: l).
Lemma IR_equiv_AAOF_I : forall k xs ys target, op_equivalent xs ys -> IR_equivalent (acknowledge_all_ops_func xs target) (acknowledge_all_ops_func ys target) -> IR_equivalent (acknowledge_all_ops_func (I k :: xs) target) (acknowledge_all_ops_func (I k :: ys) target).
Lemma IR_equiv_AAOF_II_neq : forall xs ys target k k', k <> k' -> op_equivalent xs ys -> IR_equivalent (acknowledge_all_ops_func xs target) (acknowledge_all_ops_func ys target) -> IR_equivalent (acknowledge_all_ops_func (I k :: I k' :: xs) target) (acknowledge_all_ops_func (I k' :: I k :: ys) target).
Lemma op_equiv_AAOF_IR_equiv : forall xs ys, op_equivalent xs ys -> forall l, IR_equivalent (acknowledge_all_ops_func xs l) (acknowledge_all_ops_func ys l).
Lemma op_equivalent_refl : forall xs, op_equivalent xs xs.
Lemma good_op_move_II : forall k k', good_op_move (I k) (I k').
Lemma good_op_move_neq_IO : forall k k', k <> k' -> good_op_move (I k) (O k').
Lemma good_op_move_OO : forall k k', good_op_move (O k) (O k').
Lemma op_equiv_app_tail : forall l xs ys, op_equivalent xs ys -> op_equivalent (xs ++ l) (ys ++ l).
Lemma op_equivalent_all_Is_I_middle : forall xs ys k, (forall x, In x xs -> exists k, x = I k) -> op_equivalent (xs ++ I k :: ys) (I k :: xs ++ ys).
Lemma get_op_input_keys_app : forall xs ys, get_op_input_keys (xs ++ ys) = get_op_input_keys xs ++ get_op_input_keys ys.
Lemma get_op_output_keys_app : forall xs ys, get_op_output_keys (xs ++ ys) = get_op_output_keys xs ++ get_op_output_keys ys.
Lemma get_op_input_keys_complete : forall xs k, In (I k) xs -> In k (get_op_input_keys xs).
Lemma get_op_input_keys_sound : forall k l, In k (get_op_input_keys l) -> In (I k) l.
Lemma get_op_output_keys_sound : forall k l, In k (get_op_output_keys l) -> In (O k) l.
Lemma get_op_input_keys_preserves_NoDup : forall l, NoDup l -> NoDup (get_op_input_keys l).
Lemma get_op_output_keys_preserves_NoDup : forall l, NoDup l -> NoDup (get_op_output_keys l).
Lemma get_op_output_keys_complete : forall xs k, In (O k) xs -> In k (get_op_output_keys xs).
Lemma get_IR_output_keys_complete_U : forall xs k, In (IRU k) xs -> In k (get_IR_output_keys xs).
Lemma get_IR_output_keys_complete_O : forall xs k, In (IRO k) xs -> In k (get_IR_output_keys xs).
Lemma get_IR_input_keys_complete : forall xs k, In (IRI k) xs -> In k (get_IR_input_keys xs).
Lemma op_equivalent_all_Is_O_middle : forall xs ys k, (forall k', In (I k') xs -> k <> k') -> op_equivalent (xs ++ O k :: ys) (O k :: xs ++ ys).
Lemma NoDup_get_op_output_keys_In_O : forall xs ys k, NoDup (get_op_output_keys (xs ++ O k :: ys)) -> In (O k) (xs ++ ys) -> False.
Lemma NoDup_get_op_output_keys_In_2_3 : forall xs ys zs k, NoDup (get_op_output_keys (xs ++ I k :: ys ++ O k :: zs)) -> In (O k) (xs ++ ys ++ zs) -> False.
Lemma NoDup_get_op_input_keys_In_2_3 : forall xs ys zs k, NoDup (get_op_input_keys (xs ++ I k :: ys ++ O k :: zs)) -> In (I k) (xs ++ ys ++ zs) -> False.
Lemma O_IRO_preserved_IU : forall xs ys k' ir, (forall k, In (O k) (xs ++ I k' :: ys) -> In (IRO k) (IRI k' :: IRU k' :: ir)) -> forall k, In (O k) (xs ++ ys) -> In (IRO k) ir.
Lemma O_IRO_preserved : forall xs ys zs k' ir, NoDup (get_op_output_keys (xs ++ I k' :: ys ++ O k' :: zs)) -> (forall k, In (O k) (xs ++ I k' :: ys ++ O k' :: zs) -> In (IRO k) (IRI k' :: IRO k' :: ir)) -> forall k, In (O k) (xs ++ ys ++ zs) -> In (IRO k) ir.
Lemma no_Ik_in_first2 : forall xs ys zs k, NoDup (get_op_input_keys (xs ++ I k :: ys ++ O k :: zs)) -> forall k', In (I k') (xs ++ ys) -> k <> k'.
Lemma IRO_O_preserved_IU : forall xs ys k' ir, (forall k, In (IRO k) (IRI k' :: IRU k' :: ir) -> In (O k) (xs ++ I k' :: ys)) -> forall k, In (IRO k) ir -> In (O k) (xs ++ ys).
Lemma IRO_O_preserved : forall xs ys zs k' ir, (~ In k' (get_IR_output_keys ir)) -> (forall k, In (IRO k) (IRI k' :: IRO k' :: ir) -> In (O k) (xs ++ I k' :: ys ++ O k' :: zs)) -> forall k, In (IRO k) ir -> In (O k) (xs ++ ys ++ zs).
Lemma IRU_I_preserved_IU : forall xs ys k' ir, (~ In k' (get_IR_output_keys ir)) -> (forall k, In (IRU k) (IRI k' :: IRU k' :: ir) -> In (I k) (xs ++ I k' :: ys)) -> forall k, In (IRU k) ir -> In (I k) (xs ++ ys).
Lemma IRU_I_preserved : forall xs ys zs k' ir, (~ In k' (get_IR_output_keys ir)) -> (forall k, In (IRU k) (IRI k' :: IRO k' :: ir) -> In (I k) (xs ++ I k' :: ys ++ O k' :: zs)) -> forall k, In (IRU k) ir -> In (I k) (xs ++ ys ++ zs).
Lemma NoDup_get_op_input_keys_In_I : forall xs ys k, NoDup (get_op_input_keys (xs ++ I k :: ys)) -> In (I k) (xs ++ ys) -> False.
Lemma in_before_before_preserved_IU : forall xs ys k ir, NoDup (get_op_input_keys (xs ++ I k :: ys)) -> (forall k1 k2, In (I k2) (xs ++ I k :: ys) -> before (O k1) (I k2) (xs ++ I k :: ys) -> before (IRO k1) (IRI k2) (IRI k :: IRU k :: ir)) -> forall k1 k2, In (I k2) (xs ++ ys) -> before (O k1) (I k2) (xs ++ ys) -> before (IRO k1) (IRI k2) ir.
Lemma in_before_before_preserved : forall xs ys zs k ir, NoDup (get_op_input_keys (xs ++ I k :: ys ++ O k :: zs)) -> NoDup (get_op_output_keys (xs ++ I k :: ys ++ O k :: zs)) -> (forall k1 k2, In (I k2) (xs ++ I k :: ys ++ O k :: zs) -> before (O k1) (I k2) (xs ++ I k :: ys ++ O k :: zs) -> before (IRO k1) (IRI k2) (IRI k :: IRO k :: ir)) -> forall k1 k2, In (I k2) (xs ++ ys ++ zs) -> before (O k1) (I k2) (xs ++ ys ++ zs) -> before (IRO k1) (IRI k2) ir.
Lemma in_before_preserved_IU : forall xs ys k', ~ acknowledged_op k' (xs ++ ys) -> (forall k, In (O k) (xs ++ I k' :: ys) -> before (I k) (O k) (xs ++ I k' :: ys)) -> forall k, In (O k) (xs ++ ys) -> before (I k) (O k) (xs ++ ys).
Lemma in_before_preserved : forall xs ys zs k', NoDup (get_op_output_keys (xs ++ I k' :: ys ++ O k' :: zs)) -> (forall k, In (O k) (xs ++ I k' :: ys ++ O k' :: zs) -> before (I k) (O k) (xs ++ I k' :: ys ++ O k' :: zs)) -> forall k, In (O k) (xs ++ ys ++ zs) -> before (I k) (O k) (xs ++ ys ++ zs).
Lemma IRI_I_preserved_IU : forall xs ys k' ir, (~ In k' (get_IR_input_keys ir)) -> (forall k, In (IRI k) (IRI k' :: IRU k' :: ir) -> In (I k) (xs ++ I k' :: ys)) -> forall k, In (IRI k) ir -> In (I k) (xs ++ ys).
Lemma IRI_I_preserved : forall xs ys zs k' ir, (~ In k' (get_IR_input_keys ir)) -> (forall k, In (IRI k) (IRI k' :: IRO k' :: ir) -> In (I k) (xs ++ I k' :: ys ++ O k' :: zs)) -> forall k, In (IRI k) ir -> In (I k) (xs ++ ys ++ zs).
Lemma subseq_get_op_input_keys : forall xs ys, subseq xs ys -> subseq (get_op_input_keys xs) (get_op_input_keys ys).
Lemma subseq_get_op_output_keys : forall xs ys, subseq xs ys -> subseq (get_op_output_keys xs) (get_op_output_keys ys).