Definition normalize {X} `{Finite X} (d : dist X) : dist X.
refine {|
dist_pmf := map (fun x => (x, eval_dist d (Classes.eqb x))) enum;
dist_law := _;
|}.

(* Specifications: *)
Lemma uniform_sigma_dist {X} `{Finite X} (d : dist X) f :
uniform d ->
sigma_dist d (fun x q => q * f x) ==
Qsum (map f enum) / Q_of_nat (card X).
Lemma eval_correct o :
hoare uniform uniform (eval o).
Lemma card_prod {X Y} `{Finite X, Finite Y} : card (X * Y) = (card X * card Y)%nat.
Lemma Q_of_nat_prod (x y : nat) :
Q_of_nat (x * y)%nat = Q_of_nat x * Q_of_nat y.
Lemma sumF_ext {X} `{Finite X} (f g : X -> nat) :
(forall x, f x = g x) -> sumF f = sumF g.
Lemma double_sum {X Y} (xs : list X) (ys : list Y) (f : X * Y -> nat) :
list_sum (map (fun x => list_sum (map (fun y => f (x, y)) ys)) xs) =
list_sum (map f (list_prod xs ys)).
Lemma double_sumQ {X Y} (xs : list X) (ys : list Y) (f : X * Y -> Q) :
Qsum (map (fun x => Qsum (map (fun y => f (x, y)) ys)) xs) ==
Qsum (map f (list_prod xs ys)).
Lemma list_sum_map_plus {X} (f g : X -> nat) (xs : list X) :
list_sum (map (fun x => f x + g x)%nat xs) =
(list_sum (map f xs) + list_sum (map g xs))%nat.
Lemma list_sum_map_flip {X Y} (xs : list X) (ys : list Y) (f : X -> Y -> nat) :
list_sum (map (fun x => list_sum (map (f x) ys)) xs) =
list_sum (map (fun y => list_sum (map (fun x => f x y) xs)) ys).
Lemma sum_remove : forall (a : nat) (l : list nat),
In a l ->
(a + list_sum (remove_aux Nat.eqb l a) = list_sum l)%nat.
Lemma list_sum_remove_aux_map {X} `{EqDec X} (a : X) : forall (l : list X) (f : X -> nat),
In a l ->
(list_sum (map f (remove_aux Classes.eqb l a)) =
list_sum (remove_aux Nat.eqb (map f l) (f a)))%nat.
Lemma sum_remove_map {X} `{EqDec X} (a : X) : forall (l : list X) (f : X -> nat),
In a l ->
(f a + list_sum (map f (remove_aux Classes.eqb l a)))%nat = list_sum (map f l).
Lemma sum_remove_mapQ {X} `{EqDec X} (a : X) : forall (l : list X) (f : X -> Q),
In a l ->
(f a + Qsum (map f (remove_aux Classes.eqb l a))) == Qsum (map f l).
Lemma list_sum_map_ext {X} `{EqDec X} (f : X -> nat) (l : list X) : forall (l' : list X),
NoDup l -> NoDup l' ->
(forall x, In x l -> In x l') ->
(forall x, In x l' -> In x l) ->
list_sum (map f l) = list_sum (map f l').
Lemma list_sum_map_extQ {X} `{EqDec X} (f : X -> Q) (l : list X) : forall (l' : list X),
NoDup l -> NoDup l' ->
(forall x, In x l -> In x l') ->
(forall x, In x l' -> In x l) ->
Qsum (map f l) == Qsum (map f l').
Lemma NoDup_list_prod {X Y} (xs : list X) : forall (ys : list Y),
NoDup xs -> NoDup ys -> NoDup (list_prod xs ys).
Lemma sum_2D {X Y} `{Finite X, Finite Y} (f : X * Y -> nat) :
sumF f = sumF (fun x => sumF (fun y => f (x,y))).
Lemma sumFQ_2D {X Y} `{Finite X, Finite Y} (f : X * Y -> Q) :
sumFQ f == sumFQ (fun x => sumFQ (fun y => f (x,y))).
Lemma sum_2D_flip {X Y} `{Finite X, Finite Y} (f : X -> Y -> nat) :
sumF (fun x => sumF (f x)) =
sumF (fun y => sumF (fun x => f x y)).
Lemma list_sum_indicate_empty {X} `{Finite X} (x0 : X) (xs : list X) :
~ In x0 xs ->
list_sum (map (fun x => indicate_nat (Classes.eqb x0 x)) xs) = 0%nat.
Lemma list_sum_indicate {X} `{Finite X} (x0 : X) (xs : list X) :
NoDup xs ->
In x0 xs ->
list_sum (map (fun x => indicate_nat (Classes.eqb x0 x)) xs) = 1%nat.
Lemma vertical_strip {X Y} `{Finite X, Finite Y} (x : X):
count (fun p => Classes.eqb x (fst p)) = card Y.
Lemma uniform_fst {X Y} `{Finite X, Finite Y} (d : dist (X * Y)) :
uniform d ->
uniform (monad_map fst d).