Require Export Coq.Logic.Classical.
Require Export Coq.Logic.FunctionalExtensionality.
Require Export Coq.Classes.Equivalence.
Require Export Coq.Classes.Morphisms.
Class RandomOracle: Type := {
ro_question: Type;
ro_answer: ro_question -> Type;
ro_default_question: ro_question;
ro_default_answer: ro_answer ro_default_question
}.
Definition RandomQA {ora: RandomOracle}: Type := {q: ro_question & ro_answer q}.
Definition RandomHistory {ora: RandomOracle}: Type := {h: nat -> option RandomQA | forall x y, x < y -> h x = None -> h y = None}.
Definition history_get {ora: RandomOracle} (h: RandomHistory) (n: nat) := proj1_sig h n.
Coercion history_get: RandomHistory >-> Funclass.
Tactic Notation "history_extensionality" ident(x) :=
match goal with
[ |- ?X = ?Y ] =>
apply history_extensionality; intro x
end.
Definition fin_history {ora: RandomOracle} (h: list RandomQA) : RandomHistory.
exists (fun n => nth_error h n).
intros.
rewrite nth_error_None_iff in H0 |- *.
omega.
Defined.
Definition inf_history {ora: RandomOracle} (h: nat -> RandomQA) : RandomHistory.
exists (fun n => Some (h n)).
intros.
congruence.
Defined.
Definition fstn_history {ora: RandomOracle} (n: nat) (h: RandomHistory) : RandomHistory.
exists (fun m => if le_lt_dec n m then None else h m).
intros.
destruct (le_lt_dec n x), (le_lt_dec n y); try congruence.
+ omega.
+ apply (history_sound1 h x y); auto; omega.
Defined.
Definition history_coincide {ora: RandomOracle} (n: nat) (h1 h2: RandomHistory): Prop :=
forall m, m < n -> h1 m = h2 m.
(* Definition history_cons {ora: RandomOracle} (h1: RandomHistory) (a: RandomQA) (h2: RandomHistory): Prop := exists n, history_coincide n h1 h2 /\ h1 n = None /\ h2 n = Some a /\ h2 (S n) = None. *)
Definition history_app {ora: RandomOracle} (h1 h2 h: RandomHistory): Prop :=
exists n,
h1 n = None /\
history_coincide n h1 h /\
(forall m, h (m + n) = h2 m).
Definition is_fin_history {ora: RandomOracle} (h: RandomHistory): Prop :=
exists n, h n = None.
Definition is_inf_history {ora: RandomOracle} (h: RandomHistory): Prop :=
forall n, h n <> None.
Definition is_n_history {ora: RandomOracle} (n: nat) (h: RandomHistory): Prop :=
h n = None /\ forall n', n' < n -> h n' <> None.
Definition is_at_least_n_history {ora: RandomOracle} (n: nat) (h: RandomHistory): Prop :=
forall n', n' < n -> h n' <> None.
Definition prefix_history {ora: RandomOracle} (h1 h2: RandomHistory): Prop :=
forall n, h1 n = None \/ h1 n = h2 n.
Definition strict_prefix_history {ora: RandomOracle} (h1 h2: RandomHistory): Prop :=
prefix_history h1 h2 /\ exists n, h1 n <> h2 n.
Definition n_bounded_prefix_history {ora: RandomOracle} (m: nat) (h1 h2: RandomHistory): Prop :=
forall n, (h1 n = None /\ h2 (n + m) = None) \/ h1 n = h2 n.
Definition n_conflict_history {ora: RandomOracle} (n: nat) (h1 h2: RandomHistory): Prop :=
match h1 n, h2 n with
| Some a1, Some a2 => projT1 a1 <> projT1 a2
| Some _, None => True
| None, Some _ => True
| None, None => False
end.
Definition conflict_history {ora: RandomOracle} (h1 h2: RandomHistory): Prop :=
exists n, history_coincide n h1 h2 /\ n_conflict_history n h1 h2.
Definition strict_conflict_history {ora: RandomOracle} (h1 h2: RandomHistory): Prop :=
exists n,
history_coincide n h1 h2 /\
match h1 n, h2 n with
| Some a1, Some a2 => projT1 a1 <> projT1 a2
| _, _ => False
end.

Lemma fstn_history_is_n_history {ora: RandomOracle}: forall n m h,
m <= n ->
is_n_history n h ->
is_n_history m (fstn_history m h).