Definition inj_on_list {A B} (l : list A) (f : A -> B) :=
forall x y, In x l -> In y l -> f x = f y -> x = y.
Definition subset_rel {X} (sub lst : list X) : Prop :=
forall x,
In x sub ->
In x lst.
(*** NoDup general lemmas ***)

(* Specifications: *)
(* TODO: eventually replace NoDup_disjointness with this *)
Lemma NoDup_disjointness_1: forall {A} (l1 l2 : list A),
NoDup l1 ->
NoDup l2 ->
disjoint_list l1 l2 ->
NoDup (l1 ++ l2).
Lemma NoDup_disjointness: forall {A B} (l1 : list A) (l2 : list A) (f : A -> B) ,
NoDup (List.map f l1) ->
NoDup (List.map f l2) ->
disjoint_list (List.map f l1) (List.map f l2) ->
NoDup (List.map f (l1 ++ l2)).
Lemma NoDup_app_disj : forall {A} (l1 l2 : list A),
NoDup (l1 ++ l2) ->
disjoint_list l1 l2.
Lemma NoDup_app_remove_mid : forall (A : Type) (l2 l1 l3 : list A) ,
NoDup (l1 ++ l2 ++ l3) -> NoDup (l1 ++ l3).
Lemma NoDup_takeL {A} : forall n (l : list A),
NoDup l -> NoDup (takeL n l).
Lemma NoDup_map_inj {A B} : forall (f : A -> B) l,
NoDup (List.map f l) ->
inj_on_list l f.
Lemma remove_aux_removed {A} `{EqDec A} :
forall (lst : list A) (a : A),
NoDup lst ->
~ In a (remove_aux eqb lst a).
Lemma NoDup_remove_aux_general {A} `{EqDec A} : forall lst b,
NoDup lst ->
NoDup (remove_aux eqb lst b).
Lemma remove_list_sub_removed {A} `{EqDec A} : forall dlt lst b,
NoDup lst ->
In b (remove_list_sub eqb dlt lst) ->
~ In b dlt.
(* TODO: make this generic and move elsewhere *)
Lemma NoDup_remove_aux : forall lst x,
NoDup (List.map block_blockid lst) ->
NoDup (List.map block_blockid (remove_aux eqb lst x)).
Lemma up_oram_tr_tree_or_delta o : forall id lvl dlt p,
In id (List.map block_blockid (get_all_blks_tree
(up_oram_tr o lvl dlt p))) ->
In id (List.map block_blockid (get_all_blks_tree o)) \/
In id (List.map block_blockid dlt).
Lemma NoDup_up_oram_tree : forall o dlt lvl p,
NoDup (List.map block_blockid dlt) ->
NoDup (List.map block_blockid (get_all_blks_tree o)) ->
disjoint_list (List.map block_blockid (get_all_blks_tree o))
(List.map block_blockid dlt) ->
NoDup
(List.map block_blockid
(get_all_blks_tree (up_oram_tr o lvl dlt p))).
(* TODO: make generic and move elsewhere *)
Lemma NoDup_remove_list_sub : forall (dlt lst : list block),
NoDup (List.map block_blockid lst) ->
NoDup (List.map block_blockid (remove_list_sub eqb dlt lst)).
Lemma subset_rel_get_cand_bs : forall `{C :Config} lst p lvl pos_map,
subset_rel (get_cand_bs lst p lvl pos_map) lst.
Lemma NoDup_get_write_back_blocks : forall `{C : Config} lst p lvl pos_map,
NoDup (List.map block_blockid lst) ->
NoDup (List.map block_blockid
(get_write_back_blocks p lst 4 lvl pos_map)).
Lemma disjoint_dlt : forall o lvl dlt lst p,
NoDup (List.map block_blockid lst) ->
subset_rel dlt lst ->
disjoint_list
(List.map block_blockid (get_all_blks_tree o))
(List.map block_blockid lst) ->
disjoint_list
(List.map block_blockid (get_all_blks_tree (up_oram_tr o lvl dlt p)))
(List.map block_blockid (remove_list_sub eqb dlt lst)).