Section Linearizability.
Variable K : Type.
Variable K_eq_dec : forall x y : K, {x = y} + {x <> y}.
Inductive op : Type :=
| I : K -> op
| O : K -> op.
Definition op_eq_dec :
forall x y : op, {x = y} + {x <> y}.
Proof using K_eq_dec.
decide equality.
Qed.
Inductive IR : Type :=
| IRI : K -> IR
| IRO : K -> IR
| IRU : K -> IR.
Definition IR_eq_dec :
forall x y : IR, {x = y} + {x <> y}.
Proof using K_eq_dec.
decide equality.
Qed.
(* Hypothesis trace_NoDup : NoDup trace. *)
(* also maybe: no Us *)
(* alse maybe: every O has corresponding I before it *)
Definition acknowledged_op (k : K) (trace : list op) :=
In (O k) trace.
Definition acknowledged_op_dec (k : K) (tr : list op) : {acknowledged_op k tr} + {~acknowledged_op k tr} :=
in_dec op_eq_dec (O k) tr.
Inductive acknowledge_all_ops : list op ->  list IR -> Prop :=
| AAO_nil : acknowledge_all_ops [] []
| AAO_IU : forall k tr out,
~ acknowledged_op k tr ->
acknowledge_all_ops tr out ->
acknowledge_all_ops (I k :: tr) (IRI k :: IRU k :: out)
| AAO_I_dorp : forall k tr out,
~ acknowledged_op k tr ->
acknowledge_all_ops tr out ->
acknowledge_all_ops (I k :: tr) out
| AAO_IO : forall k tr out,
acknowledged_op k tr ->
acknowledge_all_ops tr out ->
acknowledge_all_ops (I k :: tr) (IRI k :: out)
| AAO_O : forall k tr out,
acknowledge_all_ops tr out ->
acknowledge_all_ops (O k :: tr) (IRO k :: out).
Proof using.
induction 1; intros; simpl in *; intuition (auto; congruence).
Qed.
Fixpoint acknowledge_all_ops_func (l : list op) (target : list IR) : list IR :=
match l with
| [] => []
| x :: xs => match x with
| I k => if acknowledged_op_dec k xs
then IRI k :: acknowledge_all_ops_func xs target
else if in_dec IR_eq_dec (IRU k) target
then IRI k :: IRU k :: acknowledge_all_ops_func xs target
else acknowledge_all_ops_func xs target
| O k => IRO k :: acknowledge_all_ops_func xs target
end
end.
Hint Constructors acknowledge_all_ops : core.

Lemma acknowledge_all_ops_func_defn :
forall x l target,
acknowledge_all_ops_func (x :: l) target =
match x with
| I k => if acknowledged_op_dec k l
then IRI k :: acknowledge_all_ops_func l target
else if in_dec IR_eq_dec (IRU k) target
then IRI k :: IRU k :: acknowledge_all_ops_func l target
else acknowledge_all_ops_func l target
| O k => IRO k :: acknowledge_all_ops_func l target
end.