clutch.prob.countable_sum
From Stdlib Require Import Reals Psatz.
From Coquelicot Require Import Series Hierarchy Lim_seq Rbar Lub.
From stdpp Require Import option.
From stdpp Require Export countable finite gmap fin_sets.
From clutch.prelude Require Import base Reals_ext Coquelicot_ext Series_ext stdpp_ext classical fin uniform_list.
Set Default Proof Using "Type*".
Import Hierarchy.
Open Scope R.
From Coquelicot Require Import Series Hierarchy Lim_seq Rbar Lub.
From stdpp Require Import option.
From stdpp Require Export countable finite gmap fin_sets.
From clutch.prelude Require Import base Reals_ext Coquelicot_ext Series_ext stdpp_ext classical fin uniform_list.
Set Default Proof Using "Type*".
Import Hierarchy.
Open Scope R.
A theory of (in)finite series over countable types.
'Traverses' the type in the order given by decoding 0, 1, 2, ...
Definition countable_sum (f : A → R) :=
λ (n : nat), from_option f 0 (encode_inv_nat n).
Lemma countable_sum_0 f m :
(∀ n, f n = 0) → countable_sum f m = 0.
Proof. intros. rewrite /countable_sum. destruct (encode_inv_nat _); eauto. Qed.
Lemma countable_sum_ge_0 f m :
(∀ n, 0 <= f n) → 0 <= countable_sum f m.
Proof. intros. rewrite /countable_sum. destruct (encode_inv_nat _)=>//=. Qed.
Lemma countable_sum_ext f g m :
(∀ n, f n = g n) → countable_sum f m = countable_sum g m.
Proof. intros ?. rewrite /countable_sum. destruct (encode_inv_nat _) => //=. Qed.
Lemma countable_sum_le f g m :
(∀ n, f n <= g n) → countable_sum f m <= countable_sum g m.
Proof. intros ?. rewrite /countable_sum. destruct (encode_inv_nat _) =>//=. Qed.
Lemma countable_sum_scal c f n :
countable_sum (λ x, scal c (f x)) n = scal c (countable_sum f n).
Proof.
intros. rewrite //= /countable_sum /scal //= /mult //=.
destruct (encode_inv_nat _) => //=; lra.
Qed.
Lemma countable_sum_plus f g n :
countable_sum (λ x, f x + g x) n = countable_sum f n + countable_sum g n.
Proof.
intros. rewrite //=/countable_sum; destruct (encode_inv_nat) => //=. lra.
Qed.
Lemma countable_sum_minus f g n :
countable_sum (λ x, f x - g x) n = countable_sum f n - countable_sum g n.
Proof.
intros. rewrite //=/countable_sum; destruct (encode_inv_nat) => //=. lra.
Qed.
Lemma countable_sum_mult f g n :
countable_sum (λ x, f x * g x) n = countable_sum f n * countable_sum g n.
Proof.
intros. rewrite //=/countable_sum; destruct (encode_inv_nat) => //=. lra.
Qed.
Lemma countable_sum_Rabs f n :
countable_sum (λ x, Rabs (f x)) n = Rabs (countable_sum f n).
Proof.
intros. rewrite //=/countable_sum; destruct (encode_inv_nat _) => //=. rewrite Rabs_R0 //=.
Qed.
Lemma countable_sum_scal_l f c n :
countable_sum (λ x, c * f x) n = c * countable_sum f n.
Proof. apply countable_sum_scal. Qed.
Lemma countable_sum_scal_r f c n :
countable_sum (λ x, f x * c) n = countable_sum f n * c.
Proof.
intros. rewrite //=/countable_sum; destruct (encode_inv_nat) => //=. lra. Qed.
Global Instance countable_sum_Proper:
Proper (pointwise_relation A (@eq R) ==> pointwise_relation nat (@eq R)) countable_sum.
Proof. intros ?? ? x. rewrite /countable_sum. destruct (encode_inv_nat _); eauto. Qed.
Global Instance countable_sum_Proper' :
Proper (pointwise_relation A (@eq R) ==> eq ==> eq) countable_sum.
Proof. intros ?? ? ? ??. subst. eapply countable_sum_ext; eauto. Qed.
λ (n : nat), from_option f 0 (encode_inv_nat n).
Lemma countable_sum_0 f m :
(∀ n, f n = 0) → countable_sum f m = 0.
Proof. intros. rewrite /countable_sum. destruct (encode_inv_nat _); eauto. Qed.
Lemma countable_sum_ge_0 f m :
(∀ n, 0 <= f n) → 0 <= countable_sum f m.
Proof. intros. rewrite /countable_sum. destruct (encode_inv_nat _)=>//=. Qed.
Lemma countable_sum_ext f g m :
(∀ n, f n = g n) → countable_sum f m = countable_sum g m.
Proof. intros ?. rewrite /countable_sum. destruct (encode_inv_nat _) => //=. Qed.
Lemma countable_sum_le f g m :
(∀ n, f n <= g n) → countable_sum f m <= countable_sum g m.
Proof. intros ?. rewrite /countable_sum. destruct (encode_inv_nat _) =>//=. Qed.
Lemma countable_sum_scal c f n :
countable_sum (λ x, scal c (f x)) n = scal c (countable_sum f n).
Proof.
intros. rewrite //= /countable_sum /scal //= /mult //=.
destruct (encode_inv_nat _) => //=; lra.
Qed.
Lemma countable_sum_plus f g n :
countable_sum (λ x, f x + g x) n = countable_sum f n + countable_sum g n.
Proof.
intros. rewrite //=/countable_sum; destruct (encode_inv_nat) => //=. lra.
Qed.
Lemma countable_sum_minus f g n :
countable_sum (λ x, f x - g x) n = countable_sum f n - countable_sum g n.
Proof.
intros. rewrite //=/countable_sum; destruct (encode_inv_nat) => //=. lra.
Qed.
Lemma countable_sum_mult f g n :
countable_sum (λ x, f x * g x) n = countable_sum f n * countable_sum g n.
Proof.
intros. rewrite //=/countable_sum; destruct (encode_inv_nat) => //=. lra.
Qed.
Lemma countable_sum_Rabs f n :
countable_sum (λ x, Rabs (f x)) n = Rabs (countable_sum f n).
Proof.
intros. rewrite //=/countable_sum; destruct (encode_inv_nat _) => //=. rewrite Rabs_R0 //=.
Qed.
Lemma countable_sum_scal_l f c n :
countable_sum (λ x, c * f x) n = c * countable_sum f n.
Proof. apply countable_sum_scal. Qed.
Lemma countable_sum_scal_r f c n :
countable_sum (λ x, f x * c) n = countable_sum f n * c.
Proof.
intros. rewrite //=/countable_sum; destruct (encode_inv_nat) => //=. lra. Qed.
Global Instance countable_sum_Proper:
Proper (pointwise_relation A (@eq R) ==> pointwise_relation nat (@eq R)) countable_sum.
Proof. intros ?? ? x. rewrite /countable_sum. destruct (encode_inv_nat _); eauto. Qed.
Global Instance countable_sum_Proper' :
Proper (pointwise_relation A (@eq R) ==> eq ==> eq) countable_sum.
Proof. intros ?? ? ? ??. subst. eapply countable_sum_ext; eauto. Qed.
TODO: more lifted lemmas on sumC
Definition sumC_n (f : A → R) := sum_n (countable_sum f).
End countable_sum.
Section series.
Context `{Countable A}.
Implicit Types f g : A → R.
End countable_sum.
Section series.
Context `{Countable A}.
Implicit Types f g : A → R.
Lifting of the Coquliecot predicates for working with series
Definition is_seriesC f := is_series (countable_sum f).
Definition ex_seriesC f := ∃ a, is_seriesC f a.
Definition SeriesC f := Series (countable_sum f).
Lemma is_seriesC_0 f :
(∀ n, f n = 0) → is_seriesC f 0.
Proof.
intros ?. apply is_series_0=> n.
rewrite /countable_sum. destruct (encode_inv_nat _)=>/=; auto.
Qed.
Lemma is_seriesC_ext f g l :
(∀ n, f n = g n) → is_seriesC g l → is_seriesC f l.
Proof.
intros ?. apply is_series_ext=> n. by apply countable_sum_ext.
Qed.
Lemma is_seriesC_unique f l :
is_seriesC f l → SeriesC f = l.
Proof.
apply is_series_unique.
Qed.
Lemma ex_seriesC_ex_series f :
ex_series (countable_sum f) → ex_seriesC f .
Proof.
intros; auto.
Qed.
Lemma ex_seriesC_ex_series_inv f :
ex_seriesC f → ex_series (countable_sum f).
Proof.
intros; auto.
Qed.
Lemma ex_seriesC_ext f g :
(∀ n, f n = g n) → ex_seriesC f → ex_seriesC g.
Proof.
intros ?. apply ex_series_ext=> n. by apply countable_sum_ext.
Qed.
Lemma is_seriesC_chain f g v : is_seriesC g (SeriesC f) → is_seriesC f v → is_seriesC g v.
Proof.
intros Hs2 Hs1. apply is_seriesC_unique in Hs1. rewrite -Hs1. done.
Qed.
Lemma SeriesC_correct f :
ex_seriesC f → is_seriesC f (SeriesC f).
Proof. apply Series_correct. Qed.
Lemma SeriesC_correct' a v:
SeriesC a = v → ex_seriesC a → is_seriesC a v.
Proof. by intros <- ?; apply SeriesC_correct. Qed.
Lemma SeriesC_0 f :
(∀ x, f x = 0) → SeriesC f = 0.
Proof. intros Heq0. apply Series_0=> ?. by apply countable_sum_0. Qed.
Lemma SeriesC_ge_0 (f : A → R) :
(∀ x, 0 <= f x) →
ex_seriesC f →
0 <= SeriesC f.
Proof.
intros Heq0 Hex.
rewrite -(SeriesC_0 (λ _ : A, 0)); [|done].
apply Series_le; [|done].
intros n. split.
+ apply countable_sum_ge_0. intros ?; lra.
+ by apply countable_sum_le.
Qed.
Lemma SeriesC_ge_0' (f : A → R) :
(∀ x, 0 <= f x) →
0 <= SeriesC f.
Proof.
intros Heq0.
apply series_ge_0=> ?.
apply countable_sum_ge_0; intros; auto.
Qed.
Lemma SeriesC_ext f g :
(∀ n, f n = g n) → SeriesC f = SeriesC g.
Proof. intros Hext. apply Series_ext => // n. by apply countable_sum_ext. Qed.
Lemma SeriesC_le f g :
(∀ n, 0 <= f n <= g n) →
ex_seriesC g →
SeriesC f <= SeriesC g.
Proof.
intros Hrange Hex. apply Series_le => // n.
rewrite /countable_sum.
destruct (encode_inv_nat _) => //=; lra.
Qed.
Lemma SeriesC_le' f g :
(∀ n, f n <= g n) →
ex_seriesC f →
ex_seriesC g →
SeriesC f <= SeriesC g.
Proof.
intros ???. apply Series_le' => //= n.
rewrite /countable_sum.
destruct (encode_inv_nat _) => //=.
Qed.
Lemma SeriesC_scal_l f c :
SeriesC (λ x, c * f x) = c * SeriesC f.
Proof.
intros. rewrite -Series_scal_l. apply Series_ext. apply countable_sum_scal_l.
Qed.
Lemma SeriesC_scal_r f c :
SeriesC (λ x, f x * c) = SeriesC f * c.
Proof.
intros. rewrite -Series_scal_r. apply Series_ext. apply countable_sum_scal_r.
Qed.
Lemma SeriesC_plus f g :
ex_seriesC f →
ex_seriesC g →
SeriesC (λ x, f x + g x) = SeriesC f + SeriesC g.
Proof.
intros. rewrite -Series_plus //. apply Series_ext. apply countable_sum_plus.
Qed.
Lemma SeriesC_minus f g :
ex_seriesC f →
ex_seriesC g →
SeriesC (λ x, f x - g x) = SeriesC f - SeriesC g.
Proof.
intros. rewrite -Series_minus //. apply Series_ext. apply countable_sum_minus.
Qed.
Lemma ex_seriesC_0 :
ex_seriesC (λ _, 0).
Proof.
eexists; by eapply is_seriesC_0.
Qed.
Lemma ex_seriesC_le f g :
(∀ n, 0 <= f n <= g n) →
ex_seriesC g →
ex_seriesC f.
Proof.
intros Hle Hex.
eapply @ex_series_le; [|eauto].
intros n. rewrite /norm//=/abs//=.
rewrite -countable_sum_Rabs. apply countable_sum_le.
intros x. destruct (Hle x); eauto. rewrite Rabs_right; eauto; lra.
Qed.
Lemma ex_seriesC_scal_l f c :
ex_seriesC f →
ex_seriesC (λ x, c * f x).
Proof.
intros. eapply ex_series_ext.
{ intros n. rewrite countable_sum_scal_l. done. }
by eapply @ex_series_scal_l.
Qed.
Lemma ex_seriesC_scal_r f c :
ex_seriesC f →
ex_seriesC (λ x, f x * c).
Proof.
intros. eapply ex_series_ext.
{ intros n. rewrite countable_sum_scal_r. done. }
apply: ex_series_scal_r; eauto.
Qed.
Lemma ex_seriesC_plus f g :
ex_seriesC f →
ex_seriesC g →
ex_seriesC (λ x, f x + g x).
Proof.
intros. eapply ex_series_ext.
{ intros n. rewrite countable_sum_plus. done. }
apply: ex_series_plus; eauto.
Qed.
Lemma is_seriesC_scal_l f c v :
is_seriesC f v →
is_seriesC (λ x, c * f x) (c * v).
Proof.
intros. eapply is_series_ext.
{ intros n. rewrite countable_sum_scal_l. done. }
apply: is_series_scal_l; eauto.
Qed.
Lemma is_seriesC_scal_r f c v:
is_seriesC f v →
is_seriesC (λ x, f x * c) (v * c).
Proof.
intros. eapply is_series_ext.
{ intros n. rewrite countable_sum_scal_r. done. }
apply: is_series_scal_r; eauto.
Qed.
Lemma is_seriesC_plus f g v1 v2:
is_seriesC f v1 →
is_seriesC g v2 →
is_seriesC (λ x, f x + g x) (v1 + v2).
Proof.
intros. eapply is_series_ext.
{ intros n. rewrite countable_sum_plus. done. }
apply: is_series_plus; eauto.
Qed.
Lemma ex_seriesC_Rabs f :
ex_seriesC (λ x, Rabs (f x)) →
ex_seriesC f.
Proof.
intros. eapply ex_series_Rabs.
eapply ex_series_ext.
{ intros n. rewrite -countable_sum_Rabs. done. }
eauto.
Qed.
Global Instance is_series_Proper:
Proper (pointwise_relation A (@eq R) ==> @eq R ==> iff) is_seriesC.
Proof. intros ?? ? ?? ?; subst; split; eapply is_seriesC_ext; eauto. Qed.
Global Instance ex_series_Proper:
Proper (pointwise_relation A (@eq R) ==> iff) ex_seriesC.
Proof. intros ?? ?; split; eapply ex_seriesC_ext; eauto. Qed.
Global Instance Series_Proper:
Proper (pointwise_relation A (@eq R) ==> eq) SeriesC.
Proof. intros ?? ?; eapply SeriesC_ext; eauto. Qed.
End series.
Section series_nat.
Lemma encode_inv_nat_nat (n : nat) :
(encode_inv_nat n) = Some n.
Proof.
rewrite /encode_inv_nat/decode_nat/decode/nat_countable/decode/N_countable.
destruct n eqn:Hn; simpl; auto.
rewrite decide_False //=; [ | lia].
rewrite Nat2Pos.inj_succ //
positive_N_nat
Pos.pred_succ
Nat2Pos.id //
option_guard_True //
/encode_nat/encode/=.
lia.
Qed.
Lemma ex_seriesC_nat (f : nat -> R) :
ex_series f <-> ex_seriesC f.
Proof.
split; intro Hex.
- apply (ex_series_ext f); auto.
intros. rewrite /countable_sum.
rewrite encode_inv_nat_nat //.
- destruct Hex as [r Hr].
exists r.
rewrite /is_seriesC/countable_sum in Hr.
setoid_rewrite encode_inv_nat_nat in Hr.
auto.
Qed.
Lemma SeriesC_nat (f : nat -> R) :
SeriesC f = Series f.
Proof.
rewrite /SeriesC/Series/countable_sum.
f_equal.
apply Lim_seq_ext.
intro n.
apply sum_n_ext.
intro; rewrite encode_inv_nat_nat; auto.
Qed.
End series_nat.
Section filter.
Context `{Countable A, Countable B}.
Implicit Types P Q : A → Prop.
Lemma is_seriesC_singleton_dependent (a : A) v :
is_seriesC (λ (n : A), if bool_decide (n = a) then v n else 0) (v a).
Proof.
rewrite /is_seriesC.
eapply is_series_ext; [|apply (is_series_singleton (encode_nat a))].
intros n =>/=. rewrite /countable_sum.
case_bool_decide as Hneq=>/=; subst.
- rewrite encode_inv_encode_nat //= bool_decide_eq_true_2 //.
- destruct (encode_inv_nat _) eqn:Heq=>//=.
case_bool_decide; [|done]; subst.
exfalso. apply Hneq. symmetry. by apply encode_inv_Some_nat.
Qed.
Lemma is_seriesC_singleton (a : A) v :
is_seriesC (λ (n : A), if bool_decide (n = a) then v else 0) v.
Proof. apply is_seriesC_singleton_dependent. Qed.
Lemma ex_seriesC_singleton_dependent (a : A) v :
ex_seriesC (λ (n : A), if bool_decide (n = a) then v n else 0).
Proof. eexists. eapply is_seriesC_singleton_dependent. Qed.
Lemma ex_seriesC_singleton (a : A) v :
ex_seriesC (λ (n : A), if bool_decide (n = a) then v else 0).
Proof. eexists. eapply is_seriesC_singleton. Qed.
Lemma SeriesC_singleton_dependent (a : A) v :
SeriesC (λ n, if bool_decide (n = a) then v n else 0) = v a.
Proof. apply is_series_unique, is_seriesC_singleton_dependent. Qed.
Lemma SeriesC_singleton (a : A) v :
SeriesC (λ n, if bool_decide (n = a) then v else 0) = v.
Proof. apply is_series_unique, is_seriesC_singleton. Qed.
Lemma SeriesC_subset g f {_:∀ a, Decision (g a)}:
(∀ (a:A), (¬ g a) -> f a = 0)->
SeriesC f = SeriesC (λ a, if bool_decide (g a) then f a else 0).
Proof.
intros H1.
apply SeriesC_ext.
intros. case_bool_decide; first done.
naive_solver.
Qed.
Lemma is_seriesC_singleton_inj (b : B) (f : A → B) v `{Inj A B (=) (=) f} :
(∃ a, f a = b) →
is_seriesC (λ (a : A), if bool_decide (f a = b) then v else 0) v.
Proof.
intros (a & Ha).
rewrite /is_seriesC.
eapply is_series_ext; [|apply (is_series_singleton (encode_nat a))].
intros n =>/=. rewrite /countable_sum.
case_bool_decide as Hneq=>/=; subst.
- rewrite (encode_inv_encode_nat a) //= bool_decide_eq_true_2 //.
- destruct (encode_inv_nat _) eqn:Heq=>//=.
case_bool_decide; [|done]; subst.
exfalso.
specialize (H1 a0 a H2); simplify_eq.
apply Hneq. symmetry. by apply encode_inv_Some_nat.
Qed.
Lemma ex_seriesC_singleton_inj (b : B) (f : A → B) v `{Inj A B (=) (=) f} :
(∃ a, f a = b) →
ex_seriesC (λ (a : A), if bool_decide (f a = b) then v else 0).
Proof.
eexists. apply is_seriesC_singleton_inj; auto.
Qed.
Lemma SeriesC_singleton_inj (b : B) (f : A → B) v `{Inj A B (=) (=) f} :
(∃ a, f a = b) →
SeriesC (λ (a : A), if bool_decide (f a = b) then v else 0) = v.
Proof.
intros. apply is_seriesC_unique, is_seriesC_singleton_inj; auto.
Qed.
Lemma SeriesC_ge_elem (f : A → R) (a : A) :
(∀ x, 0 <= f x) →
ex_seriesC f →
f a <= SeriesC f.
Proof.
intros Hf Hex.
rewrite -(SeriesC_singleton a (f a)).
apply SeriesC_le; [|done].
intros a'. specialize (Hf a').
case_bool_decide; simplify_eq; lra.
Qed.
Lemma ex_seriesC_singleton' (a : A) v :
ex_seriesC (λ (n : A), if bool_decide (a = n) then v else 0).
Proof.
apply (ex_seriesC_ext (λ n : A, if bool_decide (n = a) then v else 0)
(λ n : A, if bool_decide (a = n) then v else 0)).
+ intro a'; rewrite (bool_decide_ext (a = a') (a' = a)); done.
+ apply ex_seriesC_singleton.
Qed.
Lemma SeriesC_singleton' (a : A) v :
SeriesC (λ n, if bool_decide (a = n) then v else 0) = v.
Proof.
rewrite (SeriesC_ext (λ n : A, if bool_decide (a = n) then v else 0)
(λ n : A, if bool_decide (n = a) then v else 0)).
+ apply SeriesC_singleton.
+ intro a'; rewrite (bool_decide_ext (a = a') (a' = a)); done.
Qed.
Lemma ex_seriesC_list (l : list A) (f : A -> R):
ex_seriesC (λ (a : A), if bool_decide(a ∈ l) then f a else 0).
Proof.
induction l.
{ eapply ex_seriesC_ext; last apply ex_seriesC_0.
intros; done.
}
destruct (decide(a ∈ l)).
{ eapply ex_seriesC_ext; last done.
intros.
simpl.
erewrite bool_decide_ext; first done.
set_solver.
}
eapply ex_seriesC_ext; last apply ex_seriesC_plus.
2:{ apply IHl. }
2:{ eapply (ex_seriesC_singleton _ (f a)). }
intros x.
simpl.
repeat case_bool_decide; try set_solver.
all: try (by subst).
all: try lra.
- subst. apply Rplus_0_l.
- subst. set_solver.
Qed.
Lemma SeriesC_list (l:list A) f:
NoDup l -> SeriesC (λ (a : A), if bool_decide(a ∈ l) then f a else 0) =
foldr (Rplus ∘ f) 0%R l.
Proof.
induction l as [|a l IHl].
- intros. simpl. apply SeriesC_0; naive_solver.
- intro Hnd. simpl. rewrite -IHl; last first.
{ inversion Hnd. done. }
erewrite <-(SeriesC_singleton_dependent _ ) at 1.
erewrite <-SeriesC_plus; last first.
{ apply ex_seriesC_list. }
{ apply ex_seriesC_singleton_dependent. }
apply SeriesC_ext.
intros.
rewrite NoDup_cons in Hnd.
destruct Hnd as [H1 H2].
repeat case_bool_decide; try lra; set_solver.
Qed.
Lemma SeriesC_list_1 (l:list A):
NoDup l -> SeriesC (λ (a : A), if bool_decide(a ∈ l) then 1 else 0) = length l.
Proof.
intros.
rewrite SeriesC_list; last done.
clear.
induction l; first (simpl;lra).
simpl. rewrite -/(INR (S _)). rewrite S_INR.
rewrite IHl. lra.
Qed.
Lemma SeriesC_list_2 (l:list A) r:
NoDup l -> SeriesC (λ (a : A), if bool_decide(a ∈ l) then r else 0) = r * length l.
Proof.
intros.
rewrite SeriesC_list; last done.
clear.
induction l; first (simpl;lra).
simpl. rewrite -/(INR (S _)). rewrite S_INR.
rewrite IHl. lra.
Qed.
Lemma ex_seriesC_finite_from_option (l : list A) (f : B -> R) (g : A -> option B):
(∀ a : A, is_Some (g a) <-> a ∈ l) ->
ex_seriesC (λ (a : A), from_option f 0%R (g a)).
Proof.
intros Hl.
eapply ex_seriesC_ext; last apply (ex_seriesC_list l).
intros a.
simpl.
case_bool_decide as H1; first done.
destruct (g a) eqn:K.
{ exfalso. apply H1. apply Hl. done. }
done.
Qed.
Lemma ex_seriesC_from_option h f:
(∀ n, 0 <= f n) ->
(∀ (n1 n2:B) (m : A), h n1 = Some m → h n2 = Some m → n1 = n2) ->
ex_seriesC f → ex_seriesC (λ a : B, from_option f 0 (h a)).
Proof.
intros Hpos Hinj H1.
apply ex_seriesC_ex_series.
apply ex_pos_bounded_series.
{ intros n.
rewrite /countable_sum.
rewrite /from_option.
repeat case_match; real_solver. }
exists (SeriesC f).
intros n.
assert (∃ l : list _,
(∀ m, m∈l->(∃ k a, (k<=n)%nat /\ (@encode_inv_nat B _ _ k%nat) = Some a /\
h a = Some m)) /\
sum_n (countable_sum (λ a : B, from_option f 0 (h a))) n <=
SeriesC (λ a, if bool_decide(a ∈ l) then f a else 0)
) as H'; last first.
{ destruct H' as [?[??]].
etrans; first exact.
apply SeriesC_le'; try done.
- intros. case_bool_decide; naive_solver.
- apply ex_seriesC_list.
}
induction n.
+ destruct (@encode_inv_nat B _ _ 0%nat) as [a|]eqn:Ha.
* destruct (h a) as [b|] eqn : Hb.
-- exists [b]. split.
++ intros. exists 0%nat, a.
repeat split; try lia; try done.
rewrite Hb. f_equal. set_solver.
++ rewrite sum_O. rewrite /countable_sum.
rewrite Ha. simpl. rewrite Hb. simpl.
erewrite SeriesC_ext.
** erewrite SeriesC_singleton_dependent. done.
** intro. simpl.
repeat case_bool_decide; set_solver.
-- exists []. split.
++ intros; set_solver.
++ rewrite sum_O. rewrite /countable_sum.
rewrite Ha. simpl. rewrite Hb. simpl.
rewrite SeriesC_0; intros; lra.
* exists []. split.
++ intros; set_solver.
++ rewrite sum_O. rewrite /countable_sum.
rewrite Ha. simpl.
rewrite SeriesC_0; intros; lra.
+ assert (0<=n)%nat as Hge0.
* lia.
* destruct IHn as [l[H2 H3]].
destruct (@encode_inv_nat B _ _ (S n)%nat) as [a|] eqn:Ha.
-- destruct (h a) as [b|] eqn : Hb.
++ exists (b::l). split.
** intros. set_unfold.
destruct H4; subst.
--- exists (S n), a. split; try lia. split; done.
--- specialize (H2 m H4).
destruct H2 as [?[?[?[??]]]].
exists x, x0. split; try lia. by split.
** rewrite sum_Sn. rewrite {2}/countable_sum.
rewrite Ha. simpl. rewrite Hb. simpl.
rewrite (SeriesC_ext _ (λ x, (if bool_decide (x=b) then f b else 0) +
if bool_decide (x∈l) then f x else 0
)); last first.
{ intros.
case_bool_decide.
- set_unfold. destruct H4.
+ case_bool_decide; last done.
case_bool_decide.
* subst. specialize (H2 b H6).
destruct H2 as [?[?[?[??]]]].
rewrite -H7 in Hb.
assert (a = x0).
{ eapply Hinj; try done. rewrite Hb. done. }
subst. exfalso.
rewrite -H4 in Ha. assert (x≠ (S n)) by lia.
apply H8. by eapply encode_inv_nat_some_inj.
* subst. lra.
+ case_bool_decide.
{ subst. specialize (H2 b H4) as [?[?[?[??]]]].
assert (x ≠ S n) by lia.
exfalso. apply H7. eapply encode_inv_nat_some_inj; try done.
rewrite Ha H5. f_equal.
by eapply Hinj.
}
case_bool_decide; try done. lra.
- repeat case_bool_decide.
+ set_solver.
+ set_solver.
+ set_solver.
+ lra.
}
rewrite SeriesC_plus; last first.
{ by apply ex_seriesC_list. }
{ by apply ex_seriesC_singleton. }
rewrite Rplus_comm. rewrite SeriesC_singleton.
trans ((sum_n (countable_sum (λ a0 : B, from_option f 0 (h a0))) n) + f b); try lra.
done.
++ exists l. split.
** intros. specialize (H2 _ H4) as [?[?[?[??]]]].
exists x, x0. repeat split; try done. lia.
** rewrite sum_Sn. rewrite {2}/countable_sum. rewrite Ha. simpl.
rewrite Hb. simpl. etrans; last exact.
by rewrite plus_zero_r.
-- exists l. split.
++ intros. specialize (H2 _ H4) as [?[?[?[??]]]].
exists x, x0. repeat split; try done. lia.
++ rewrite sum_Sn. rewrite {2}/countable_sum. rewrite Ha. simpl.
etrans; last exact.
by rewrite plus_zero_r.
Qed.
Lemma is_seriesC_filter_pos f v P `{∀ x, Decision (P x)} :
(∀ n, 0 <= f n) →
is_seriesC f v →
ex_seriesC (λ n, if bool_decide (P n) then f n else 0).
Proof.
intros Hge Hconv.
apply: ex_seriesC_le; last by (exists v; eauto).
intros n. rewrite /norm /= /abs.
specialize (Hge n). case_bool_decide; lra.
Qed.
Lemma is_seriesC_filter_impl f v P Q `{∀ x, Decision (P x), ∀ x, Decision (Q x)} :
(∀ n, 0 <= f n) →
is_seriesC (λ n, if bool_decide (P n) then f n else 0) v →
(∀ n, Q n → P n) →
ex_seriesC (λ n, if bool_decide (Q n) then f n else 0).
Proof.
intros Hge Hconv Himp. apply ex_seriesC_Rabs.
apply: ex_seriesC_le; last by (exists v; eauto).
intros n. rewrite /norm//=/abs//=.
specialize (Hge n). specialize (Himp n).
do 2 case_bool_decide; try (rewrite Rabs_right; auto; lra).
tauto.
Qed.
Lemma ex_seriesC_filter_impl f P Q `{∀ x, Decision (P x), ∀ x, Decision (Q x)} :
(∀ n, 0 <= f n) →
ex_seriesC (λ n, if bool_decide (P n) then f n else 0) →
(∀ n, Q n → P n) →
ex_seriesC (λ n, if bool_decide (Q n) then f n else 0).
Proof. intros ? [? ?] ?. eapply is_seriesC_filter_impl; eauto. Qed.
Lemma ex_seriesC_filter_pos f P `{∀ x, Decision (P x)} :
(∀ n, 0 <= f n) →
ex_seriesC f →
ex_seriesC (λ n, if bool_decide (P n) then f n else 0).
Proof. intros ? [v His]. by eapply is_seriesC_filter_pos. Qed.
Lemma SeriesC_filter_leq f P `{∀ x, Decision (P x)} :
(∀ n, 0 <= f n) →
ex_seriesC f →
SeriesC (λ n, if bool_decide (P n) then f n else 0) <= SeriesC f.
Proof. intros ? ?.
apply SeriesC_le; auto.
intro n; case_bool_decide; simpl; split; auto; lra.
Qed.
(* TODO: make a SeriesC_minus lemma and cleanup proof *)
Lemma is_seriesC_filter_union f v P Q `{∀ x, Decision (P x), ∀ x, Decision (Q x)} :
(∀ n, 0 <= f n) →
is_seriesC (λ n, if bool_decide (P n ∨ Q n) then f n else 0) v →
SeriesC (λ n, if bool_decide (P n) then f n else 0) +
SeriesC (λ n, if bool_decide (Q n) then f n else 0) -
SeriesC (λ n, if bool_decide (P n ∧ Q n) then f n else 0) = v.
Proof.
intros Hge Hexists.
rewrite -SeriesC_plus; last first.
{apply (is_seriesC_filter_impl _ _ _ _ Hge Hexists); eauto. }
{ apply (is_seriesC_filter_impl _ _ _ _ Hge Hexists); eauto. }
rewrite -SeriesC_minus.
- rewrite -(is_seriesC_unique _ v Hexists).
apply SeriesC_ext => n.
do 2 repeat case_bool_decide=>//=; try tauto; lra.
- apply: (ex_seriesC_le _ (λ a, scal 2 (if bool_decide (P a ∨ Q a) then f a else 0))).
+ intros a. rewrite /scal /= /mult /=.
specialize (Hge a). do 3 case_bool_decide => /=; try (lra || tauto).
+ eexists. by eapply is_seriesC_scal_l.
- eapply (is_seriesC_filter_impl _ _ _ _ Hge Hexists). intros ? []; auto.
Qed.
Lemma ex_seriesC_split_elem f (a0 : A) :
ex_seriesC (λ a, if bool_decide (a ≠ a0) then f a else 0) → ex_seriesC f.
Proof.
intros Ha0.
eapply (ex_seriesC_ext (λ a, (λ a, if bool_decide (a = a0) then f a else 0) a +
(λ a, if bool_decide (a ≠ a0) then f a else 0) a)).
{ intros a. case_bool_decide; simplify_eq.
- rewrite bool_decide_eq_false_2; [lra|auto].
- rewrite bool_decide_eq_true_2 //. lra. }
eapply ex_seriesC_plus; [|done].
eapply ex_seriesC_ext; [|eapply (ex_seriesC_singleton a0 (f a0))].
intros a. simpl. by case_bool_decide; simplify_eq.
Qed.
Lemma SeriesC_split_elem f (a0 : A) :
(∀ a, 0 <= f a) → (* TODO: this requirements should not be necessary? *)
ex_seriesC f →
SeriesC f = SeriesC (λ a, if bool_decide (a = a0) then f a else 0) +
SeriesC (λ a, if bool_decide (a ≠ a0) then f a else 0).
Proof.
intros Hle Hex.
erewrite SeriesC_ext.
{ eapply SeriesC_plus; [by eapply ex_seriesC_filter_pos|].
eapply (ex_seriesC_le _ f); [|done].
intros a'. case_bool_decide; split; (done || lra). }
intros a. simpl. case_bool_decide as Heq.
- rewrite bool_decide_eq_false_2; [lra|]. eauto.
- rewrite bool_decide_eq_true_2 //. lra.
Qed.
Lemma SeriesC_split_pred f (P : A -> bool) :
(∀ a, 0 <= f a) →
ex_seriesC f →
SeriesC f = SeriesC (λ a, if P a then f a else 0) +
SeriesC (λ a, if P a then 0 else f a).
Proof.
intros Hle Hex.
rewrite -SeriesC_plus.
- apply SeriesC_ext; intro.
destruct (P _); lra.
- apply (ex_seriesC_le _ f); auto.
intro; real_solver.
- apply (ex_seriesC_le _ f); auto.
intro; real_solver.
Qed.
Lemma ex_seriesC_filter_bool_pos f (P : A → bool) :
(∀ a, 0 <= f a) →
ex_seriesC f →
ex_seriesC (λ a, if P a then f a else 0).
Proof.
intros Hpos Hex.
apply (ex_seriesC_le _ f); auto.
intro n; specialize (Hpos n); destruct (P n); lra.
Qed.
Lemma SeriesC_pos (f : A → R) a :
(∀ a, 0 <= f a) →
ex_seriesC f →
f a > 0 →
SeriesC f > 0.
Proof.
intros Hpos Hex Ha.
rewrite (SeriesC_split_elem _ a); [|done|done].
rewrite SeriesC_singleton_dependent.
assert (0 <= SeriesC (λ a', if bool_decide (a' ≠ a) then f a' else 0)); [|lra].
eapply SeriesC_ge_0' => a'.
by case_bool_decide.
Qed.
End filter.
Lemma ex_seriesC_list_length `{Finite A} (f:list A -> R) num:
(forall x, (0≠f x)%R -> length x = num) ->
ex_seriesC f.
Proof.
intros.
eapply (ex_seriesC_ext (λ x, if bool_decide(x∈enum_uniform_list num) then f x else 0))%R.
- intros n.
case_bool_decide as K; first done.
destruct (Req_dec (f n) 0); first done.
exfalso.
apply K. apply elem_of_enum_uniform_list.
naive_solver.
- apply ex_seriesC_list.
Qed.
Lemma SeriesC_Series_nat (f : nat → R) :
SeriesC f = Series f.
Proof.
rewrite /SeriesC.
erewrite Series_ext; [done|].
rewrite /countable_sum /from_option /= => n.
case_match eqn:He.
- by apply encode_inv_nat_Some_inj in He as ->.
- by apply encode_inv_nat_None in He.
Qed.
Lemma is_seriesC_is_series_nat (f : nat → R) v :
is_series f v → is_seriesC f v.
Proof.
intros Hf.
eapply is_series_ext; [|done]=> n.
rewrite /is_seriesC /countable_sum /from_option /=.
case_match eqn:He.
- by apply encode_inv_nat_Some_inj in He as ->.
- by apply encode_inv_nat_None in He.
Qed.
Lemma SeriesC_bool (f : bool → R) :
SeriesC f = f true + f false.
Proof.
rewrite (SeriesC_ext _ (λ b, (if bool_decide (b = true) then f true else 0) +
if bool_decide (b = false) then f false else 0)).
{ rewrite SeriesC_plus; [|eapply ex_seriesC_singleton..].
rewrite 2!SeriesC_singleton //. }
intros []; simpl; lra.
Qed.
Lemma SeriesC_fin2 (f : fin 2 → R) :
SeriesC f = f 0%fin + f 1%fin.
Proof.
rewrite (SeriesC_ext _ (λ b, (if bool_decide (b = 0%fin) then f 0%fin else 0) +
if bool_decide (b = 1%fin) then f 1%fin else 0)).
{ rewrite SeriesC_plus; [|eapply ex_seriesC_singleton..].
rewrite 2!SeriesC_singleton //. }
intros n; inv_fin n; [simpl; lra|].
intros n; inv_fin n; [simpl; lra|].
intros n; inv_fin n.
Qed.
Lemma ex_seriesC_nat_bounded (f : nat -> R) (N : nat) :
ex_seriesC (λ (n : nat), if bool_decide ((n <= N)%nat) then f n else 0).
Proof.
induction N.
- apply (ex_seriesC_ext (λ n : nat, if bool_decide (n = 0%nat) then f 0%nat else 0)); [ | apply ex_seriesC_singleton ].
intro; do 2 case_bool_decide; simplify_eq; try lia; try lra.
- eapply (ex_seriesC_ext); last first.
+ apply ex_seriesC_plus; [ apply IHN | ].
apply (ex_seriesC_singleton (S N) (f (S N))).
+ intros; do 3 case_bool_decide; simplify_eq; try lia; try lra.
Qed.
Lemma ex_seriesC_nat_bounded_Zle (f : nat -> R) (z : Z) :
ex_seriesC (λ (n : nat), if bool_decide (Z.of_nat n <= z)%Z then f n else 0).
Proof.
destruct (Z_lt_ge_dec z 0) as [H|H].
- eapply ex_seriesC_ext; [ | apply ex_seriesC_0].
intro n.
rewrite bool_decide_eq_false_2; auto.
lia.
- eapply ex_seriesC_ext; [ | apply (ex_seriesC_nat_bounded f (Z.to_nat z))].
intro n.
case_bool_decide.
+ rewrite bool_decide_eq_true_2; auto.
zify.
lia.
+ rewrite bool_decide_eq_false_2; auto.
zify.
lia.
Qed.
Lemma ex_seriesC_nat_bounded_Rle (f : nat -> R) (N : nat) :
ex_seriesC (λ (n : nat), if bool_decide (n <= N) then f n else 0).
Proof.
eapply ex_seriesC_ext; [ | apply (ex_seriesC_nat_bounded f N)].
intro.
case_bool_decide.
- rewrite bool_decide_eq_true_2; auto.
by apply INR_le.
- rewrite bool_decide_eq_false_2; auto.
apply Nat.lt_nge.
apply INR_lt.
lra.
Qed.
Lemma ex_seriesC_nat_eventually_zero (f : nat -> R) (N : nat) (M : nat) :
(forall n : nat, M <= n -> f n = 0) ->
ex_seriesC f.
Proof.
intros H.
eapply ex_seriesC_ext; last first.
{ eapply (ex_seriesC_nat_bounded_Rle f M). }
intros n.
simpl; case_bool_decide; auto.
rewrite H //.
lra.
Qed.
Lemma SeriesC_nat_bounded (f : nat -> R) (N : nat) :
SeriesC (λ (n : nat), if bool_decide ((n <= N)%nat) then f n else 0) = sum_n f N.
Proof.
induction N.
- rewrite sum_O.
rewrite (SeriesC_ext _ (λ n : nat, if bool_decide (n = 0%nat) then f 0%nat else 0)).
{
apply SeriesC_singleton.
}
intros n.
pose proof (pos_INR n).
case_bool_decide as H2; case_bool_decide as H3;
simplify_eq; auto.
+ inversion H2; done.
+ destruct H2; auto.
- rewrite sum_Sn //.
rewrite -IHN.
rewrite -(SeriesC_singleton (S N) (f (S N))).
rewrite /plus/=.
rewrite -SeriesC_plus.
+ apply SeriesC_ext.
intro.
do 3 case_bool_decide; simplify_eq; try lia; try lra.
+ apply ex_seriesC_nat_bounded.
+ apply ex_seriesC_singleton.
Qed.
Lemma SeriesC_split_first (f : nat -> R) :
(∀ n, 0 <= f n) → (* TODO: this requirements should not be necessary? *)
ex_seriesC f →
SeriesC f = (f 0%nat) + SeriesC (λ n, f (S n)).
Proof.
intros Hle Hex.
rewrite (SeriesC_split_elem f 0%nat); auto.
rewrite SeriesC_singleton_dependent.
f_equal; auto.
rewrite SeriesC_nat.
rewrite SeriesC_nat.
rewrite Series_incr_1_aux.
- apply Series_ext.
intro n.
rewrite bool_decide_eq_true_2; [done|lia].
- rewrite bool_decide_eq_false_2; [done|lia].
Qed.
Section strict.
Context `{Countable A}.
Implicit Types f g : A → R.
Lemma SeriesC_lt f g :
(∀ n, 0 <= f n <= g n) →
(∃ m, f m < g m) →
ex_seriesC g →
SeriesC f < SeriesC g.
Proof.
intros Hle Hlt Hg.
assert (ex_seriesC f) as Hf.
{ apply (ex_seriesC_le f g); auto. }
destruct Hlt as (m & Hlt).
assert (g m - f m > 0) as Hgtz ; try lra.
set (d := g m - f m).
set (h := (λ n, if bool_decide (n = m) then d else 0) ).
assert (ex_seriesC h) as Hh.
{ apply ex_seriesC_singleton. }
assert (SeriesC h > 0) as Hhgt.
{ rewrite SeriesC_singleton; auto. }
assert (SeriesC f + SeriesC h <= SeriesC g); try lra.
rewrite <- SeriesC_plus; auto.
apply SeriesC_le; auto.
intro n.
specialize (Hle n) as (Hle1 & Hle2).
rewrite /h /d.
case_bool_decide as Hnm; split; try lra.
rewrite Hnm; lra.
Qed.
Lemma SeriesC_const0 f :
(∀ n, 0 <= f n) →
is_seriesC f 0 →
(∀ n, f n = 0).
Proof.
intros Hf Hz n.
pose proof (is_seriesC_unique _ _ Hz) as Hz'.
pose proof (Rtotal_order (f n) 0) as Htri.
destruct Htri as [H1 | [H2 | H3]] ; try lra.
- specialize (Hf n); lra.
- assert (0 < SeriesC f); try lra.
assert (SeriesC (λ _ : A, 0) = 0) as H4.
{ apply SeriesC_0; auto. }
destruct H4.
eapply (SeriesC_lt (λ n, 0) f).
+ intro n0; specialize (Hf n0); lra.
+ exists n; lra.
+ exists 0; done.
Qed.
Lemma SeriesC_gtz_ex f :
(∀ n, 0 <= f n) →
SeriesC f > 0 →
∃ n, f n > 0.
Proof.
intro Hf.
eapply contrapositive. intros Hna.
assert (∀ a, f a = 0) as Hz.
{ intros a.
pose proof (not_exists_forall_not _ _ Hna a).
specialize (Hf a); lra. }
apply Rge_not_gt. rewrite SeriesC_0 //.
Qed.
End strict.
Section finite.
Context `{Finite A}.
Lemma ex_seriesC_finite (f : A → R) :
ex_seriesC f.
Proof.
apply ex_series_eventually0.
exists (card A).
intros n Hn.
rewrite /countable_sum /=.
destruct (encode_inv_nat _) as [a|] eqn:Heq=>//=.
pose proof (encode_lt_card a).
rewrite /encode_inv_nat in Heq.
destruct (decode_nat n); simplify_option_eq.
lia.
Qed.
Lemma SeriesC_finite_foldr (f : A → R) :
SeriesC f = foldr (Rplus ∘ f) 0%R (enum A).
Proof.
rewrite /SeriesC /countable_sum.
setoid_rewrite encode_inv_nat_finite.
generalize (enum A).
induction l.
{ apply Series_0. eauto. }
rewrite Series_incr_1.
{ rewrite IHl //. }
eapply ex_series_ext;
[|eapply ex_seriesC_nat, (ex_seriesC_nat_bounded _ (length l + 1))].
intros n => /=.
case_bool_decide; [done|].
rewrite lookup_ge_None_2 //=. lia.
Qed.
Lemma SeriesC_finite_mass v :
SeriesC (λ _ : A, v) = card A * v.
Proof.
rewrite /SeriesC.
rewrite -(Series_ext (λ n, if bool_decide (n < card A)%nat then v else 0)); last first.
{ intros n. rewrite /countable_sum /=.
case_bool_decide as Hn; simpl.
- destruct (encode_inv_nat) eqn:Heq; [done|]; simpl.
destruct (encode_inv_decode _ Hn) as (a & Hinv & He).
simplify_option_eq.
- destruct (encode_inv_nat) eqn:Heq; [|done]; simpl.
rewrite encode_inv_decode_ge in Heq; [done|lia]. }
apply (SeriesC_leq (card A) v).
Qed.
Lemma SeriesC_finite_bound (f : A → R) v :
(∀ a, 0 <= f a <= v) →
SeriesC f <= card A * v.
Proof.
intros Hf.
rewrite -SeriesC_finite_mass.
apply SeriesC_le ; [done|].
apply ex_seriesC_finite.
Qed.
#[local] Fixpoint Rmax_seq (f : nat -> R) n :=
match n with
| 0 => f 0%nat
| S m => Rmax (f (S m)) (Rmax_seq f m)
end.
#[local] Lemma le_Rmax_seq (f : nat -> R) n m :
(m ≤ n) ->
(f m <= Rmax_seq f n)%R.
Proof.
intros Hleq.
induction Hleq.
- destruct m; simpl; [lra|].
apply Rmax_l.
- simpl.
etrans; eauto.
apply Rmax_r.
Qed.
Lemma fin_function_bounded (N : nat) (f : fin N -> R) :
exists r, forall n, (f n <= r)%R.
Proof.
induction N as [|M].
- exists 0.
intros.
by apply Fin.case0.
- set (g := (λ (n : nat), f (fin.fin_force _ n))).
exists (Rmax_seq g M).
intros n.
pose proof (fin_to_nat_lt n).
transitivity (g n).
+ rewrite /g /=.
right.
f_equal.
apply fin_to_nat_inj.
rewrite fin.fin_force_to_nat_le; lia.
+ apply le_Rmax_seq; lia.
Qed.
End finite.
(* We might need the results below to reason about uniform distributions *)
Definition extend_fin_to_R {n : nat} (f: fin n -> R) : (nat->R) :=
fun x =>
match le_lt_dec n x with
| left _ => 0%R
| right h => f (nat_to_fin h)
end.
Local Lemma foldr_ext_strong {A B} (f1 f2 : B → A → A) x1 l1 :
(∀ b a, b∈ l1 -> f1 b a = f2 b a) → foldr f1 x1 l1 = foldr f2 x1 l1.
Proof. revert x1.
induction l1.
- naive_solver.
- intros. simpl. rewrite IHl1.
+ rewrite H; [done|set_solver].
+ intros. set_unfold. naive_solver.
Qed.
Lemma SeriesC_fin_sum {n : nat} (f : fin (S n) -> R) :
SeriesC f = sum_n (extend_fin_to_R f) n.
Proof.
rewrite SeriesC_finite_foldr.
rewrite <- seq_enum_fin.
revert f. induction n.
- naive_solver.
- intros. rewrite sum_n_shift'. rewrite Rplus_comm.
rewrite -cons_seq fmap_cons foldr_cons.
assert (forall x y, (Rplus ∘ f) x y = f x + y) as -> by naive_solver.
f_equal. rewrite -fmap_S_seq -list_fmap_compose.
replace (foldr (Rplus ∘ f) 0
((λ x : nat, match le_lt_dec (S (S n)) x with
| left _ => 0%fin
| right h => nat_to_fin h
end) ∘ S <$> seq 0 (S n))) with
(foldr (Rplus ∘ (λ x, f (FS x))) 0
((λ x : nat, match le_lt_dec (S n) x with
| left _ => 0%fin
| right h => nat_to_fin h
end) <$> seq 0 (S n))).
+ rewrite IHn.
apply sum_n_ext_loc.
clear.
intros x Hx.
rewrite /extend_fin_to_R.
repeat case_match; try lia.
f_equal. apply fin_to_nat_inj.
simpl. by rewrite !fin_to_nat_to_fin.
+ clear.
rewrite !foldr_fmap. apply foldr_ext_strong.
intros b a. rewrite elem_of_seq.
intros Hb. simpl. repeat case_match; try lia.
* do 3 f_equal.
* do 3 f_equal. apply fin_to_nat_inj. simpl. by rewrite !fin_to_nat_to_fin.
Qed.
Lemma SeriesC_nat_bounded_fin f N:
SeriesC (λ n : nat, if bool_decide (n ≤ N) then f n else 0) =
SeriesC (λ n:(fin (S N)), f (fin_to_nat n)).
Proof.
rewrite SeriesC_fin_sum.
rewrite SeriesC_nat_bounded.
apply sum_n_ext_loc.
intros n ?.
rewrite /extend_fin_to_R.
case_match; first lia.
by rewrite fin_to_nat_to_fin.
Qed.
Lemma SeriesC_nat_bounded_to_foldr (f : nat -> R) (N : nat) :
SeriesC (λ (n : nat), if bool_decide ((n <= N)%nat) then f n else 0) = foldr (Rplus ∘ f ∘ fin_to_nat) 0%R (enum (fin (S N))).
Proof.
rewrite SeriesC_nat_bounded_fin.
by rewrite SeriesC_finite_foldr.
Qed.
Lemma SeriesC_nat_bounded_to_foldr' (f : nat -> R) (N : nat) :
SeriesC (λ (n : nat), if bool_decide ((n <= N)%nat) then f n else 0) = foldr Rplus 0%R ( f <$> seq 0 (S N)).
Proof.
rewrite SeriesC_nat_bounded_fin.
rewrite -enum_fin_seq.
rewrite SeriesC_finite_foldr.
assert (forall {A B} (l : list A) (h2 : B -> R) (h1 : A -> B),
foldr (Rplus ∘ h2 ∘ h1 ) 0 l = foldr (Rplus ∘ h2) 0 (h1 <$> l)) as Haux.
{
induction l.
- intros l.
simpl. done.
- intros h1 h2.
simpl.
f_equal.
auto.
}
rewrite -Haux.
rewrite -Haux.
apply foldr_ext; auto.
Qed.
Definition ex_seriesC f := ∃ a, is_seriesC f a.
Definition SeriesC f := Series (countable_sum f).
Lemma is_seriesC_0 f :
(∀ n, f n = 0) → is_seriesC f 0.
Proof.
intros ?. apply is_series_0=> n.
rewrite /countable_sum. destruct (encode_inv_nat _)=>/=; auto.
Qed.
Lemma is_seriesC_ext f g l :
(∀ n, f n = g n) → is_seriesC g l → is_seriesC f l.
Proof.
intros ?. apply is_series_ext=> n. by apply countable_sum_ext.
Qed.
Lemma is_seriesC_unique f l :
is_seriesC f l → SeriesC f = l.
Proof.
apply is_series_unique.
Qed.
Lemma ex_seriesC_ex_series f :
ex_series (countable_sum f) → ex_seriesC f .
Proof.
intros; auto.
Qed.
Lemma ex_seriesC_ex_series_inv f :
ex_seriesC f → ex_series (countable_sum f).
Proof.
intros; auto.
Qed.
Lemma ex_seriesC_ext f g :
(∀ n, f n = g n) → ex_seriesC f → ex_seriesC g.
Proof.
intros ?. apply ex_series_ext=> n. by apply countable_sum_ext.
Qed.
Lemma is_seriesC_chain f g v : is_seriesC g (SeriesC f) → is_seriesC f v → is_seriesC g v.
Proof.
intros Hs2 Hs1. apply is_seriesC_unique in Hs1. rewrite -Hs1. done.
Qed.
Lemma SeriesC_correct f :
ex_seriesC f → is_seriesC f (SeriesC f).
Proof. apply Series_correct. Qed.
Lemma SeriesC_correct' a v:
SeriesC a = v → ex_seriesC a → is_seriesC a v.
Proof. by intros <- ?; apply SeriesC_correct. Qed.
Lemma SeriesC_0 f :
(∀ x, f x = 0) → SeriesC f = 0.
Proof. intros Heq0. apply Series_0=> ?. by apply countable_sum_0. Qed.
Lemma SeriesC_ge_0 (f : A → R) :
(∀ x, 0 <= f x) →
ex_seriesC f →
0 <= SeriesC f.
Proof.
intros Heq0 Hex.
rewrite -(SeriesC_0 (λ _ : A, 0)); [|done].
apply Series_le; [|done].
intros n. split.
+ apply countable_sum_ge_0. intros ?; lra.
+ by apply countable_sum_le.
Qed.
Lemma SeriesC_ge_0' (f : A → R) :
(∀ x, 0 <= f x) →
0 <= SeriesC f.
Proof.
intros Heq0.
apply series_ge_0=> ?.
apply countable_sum_ge_0; intros; auto.
Qed.
Lemma SeriesC_ext f g :
(∀ n, f n = g n) → SeriesC f = SeriesC g.
Proof. intros Hext. apply Series_ext => // n. by apply countable_sum_ext. Qed.
Lemma SeriesC_le f g :
(∀ n, 0 <= f n <= g n) →
ex_seriesC g →
SeriesC f <= SeriesC g.
Proof.
intros Hrange Hex. apply Series_le => // n.
rewrite /countable_sum.
destruct (encode_inv_nat _) => //=; lra.
Qed.
Lemma SeriesC_le' f g :
(∀ n, f n <= g n) →
ex_seriesC f →
ex_seriesC g →
SeriesC f <= SeriesC g.
Proof.
intros ???. apply Series_le' => //= n.
rewrite /countable_sum.
destruct (encode_inv_nat _) => //=.
Qed.
Lemma SeriesC_scal_l f c :
SeriesC (λ x, c * f x) = c * SeriesC f.
Proof.
intros. rewrite -Series_scal_l. apply Series_ext. apply countable_sum_scal_l.
Qed.
Lemma SeriesC_scal_r f c :
SeriesC (λ x, f x * c) = SeriesC f * c.
Proof.
intros. rewrite -Series_scal_r. apply Series_ext. apply countable_sum_scal_r.
Qed.
Lemma SeriesC_plus f g :
ex_seriesC f →
ex_seriesC g →
SeriesC (λ x, f x + g x) = SeriesC f + SeriesC g.
Proof.
intros. rewrite -Series_plus //. apply Series_ext. apply countable_sum_plus.
Qed.
Lemma SeriesC_minus f g :
ex_seriesC f →
ex_seriesC g →
SeriesC (λ x, f x - g x) = SeriesC f - SeriesC g.
Proof.
intros. rewrite -Series_minus //. apply Series_ext. apply countable_sum_minus.
Qed.
Lemma ex_seriesC_0 :
ex_seriesC (λ _, 0).
Proof.
eexists; by eapply is_seriesC_0.
Qed.
Lemma ex_seriesC_le f g :
(∀ n, 0 <= f n <= g n) →
ex_seriesC g →
ex_seriesC f.
Proof.
intros Hle Hex.
eapply @ex_series_le; [|eauto].
intros n. rewrite /norm//=/abs//=.
rewrite -countable_sum_Rabs. apply countable_sum_le.
intros x. destruct (Hle x); eauto. rewrite Rabs_right; eauto; lra.
Qed.
Lemma ex_seriesC_scal_l f c :
ex_seriesC f →
ex_seriesC (λ x, c * f x).
Proof.
intros. eapply ex_series_ext.
{ intros n. rewrite countable_sum_scal_l. done. }
by eapply @ex_series_scal_l.
Qed.
Lemma ex_seriesC_scal_r f c :
ex_seriesC f →
ex_seriesC (λ x, f x * c).
Proof.
intros. eapply ex_series_ext.
{ intros n. rewrite countable_sum_scal_r. done. }
apply: ex_series_scal_r; eauto.
Qed.
Lemma ex_seriesC_plus f g :
ex_seriesC f →
ex_seriesC g →
ex_seriesC (λ x, f x + g x).
Proof.
intros. eapply ex_series_ext.
{ intros n. rewrite countable_sum_plus. done. }
apply: ex_series_plus; eauto.
Qed.
Lemma is_seriesC_scal_l f c v :
is_seriesC f v →
is_seriesC (λ x, c * f x) (c * v).
Proof.
intros. eapply is_series_ext.
{ intros n. rewrite countable_sum_scal_l. done. }
apply: is_series_scal_l; eauto.
Qed.
Lemma is_seriesC_scal_r f c v:
is_seriesC f v →
is_seriesC (λ x, f x * c) (v * c).
Proof.
intros. eapply is_series_ext.
{ intros n. rewrite countable_sum_scal_r. done. }
apply: is_series_scal_r; eauto.
Qed.
Lemma is_seriesC_plus f g v1 v2:
is_seriesC f v1 →
is_seriesC g v2 →
is_seriesC (λ x, f x + g x) (v1 + v2).
Proof.
intros. eapply is_series_ext.
{ intros n. rewrite countable_sum_plus. done. }
apply: is_series_plus; eauto.
Qed.
Lemma ex_seriesC_Rabs f :
ex_seriesC (λ x, Rabs (f x)) →
ex_seriesC f.
Proof.
intros. eapply ex_series_Rabs.
eapply ex_series_ext.
{ intros n. rewrite -countable_sum_Rabs. done. }
eauto.
Qed.
Global Instance is_series_Proper:
Proper (pointwise_relation A (@eq R) ==> @eq R ==> iff) is_seriesC.
Proof. intros ?? ? ?? ?; subst; split; eapply is_seriesC_ext; eauto. Qed.
Global Instance ex_series_Proper:
Proper (pointwise_relation A (@eq R) ==> iff) ex_seriesC.
Proof. intros ?? ?; split; eapply ex_seriesC_ext; eauto. Qed.
Global Instance Series_Proper:
Proper (pointwise_relation A (@eq R) ==> eq) SeriesC.
Proof. intros ?? ?; eapply SeriesC_ext; eauto. Qed.
End series.
Section series_nat.
Lemma encode_inv_nat_nat (n : nat) :
(encode_inv_nat n) = Some n.
Proof.
rewrite /encode_inv_nat/decode_nat/decode/nat_countable/decode/N_countable.
destruct n eqn:Hn; simpl; auto.
rewrite decide_False //=; [ | lia].
rewrite Nat2Pos.inj_succ //
positive_N_nat
Pos.pred_succ
Nat2Pos.id //
option_guard_True //
/encode_nat/encode/=.
lia.
Qed.
Lemma ex_seriesC_nat (f : nat -> R) :
ex_series f <-> ex_seriesC f.
Proof.
split; intro Hex.
- apply (ex_series_ext f); auto.
intros. rewrite /countable_sum.
rewrite encode_inv_nat_nat //.
- destruct Hex as [r Hr].
exists r.
rewrite /is_seriesC/countable_sum in Hr.
setoid_rewrite encode_inv_nat_nat in Hr.
auto.
Qed.
Lemma SeriesC_nat (f : nat -> R) :
SeriesC f = Series f.
Proof.
rewrite /SeriesC/Series/countable_sum.
f_equal.
apply Lim_seq_ext.
intro n.
apply sum_n_ext.
intro; rewrite encode_inv_nat_nat; auto.
Qed.
End series_nat.
Section filter.
Context `{Countable A, Countable B}.
Implicit Types P Q : A → Prop.
Lemma is_seriesC_singleton_dependent (a : A) v :
is_seriesC (λ (n : A), if bool_decide (n = a) then v n else 0) (v a).
Proof.
rewrite /is_seriesC.
eapply is_series_ext; [|apply (is_series_singleton (encode_nat a))].
intros n =>/=. rewrite /countable_sum.
case_bool_decide as Hneq=>/=; subst.
- rewrite encode_inv_encode_nat //= bool_decide_eq_true_2 //.
- destruct (encode_inv_nat _) eqn:Heq=>//=.
case_bool_decide; [|done]; subst.
exfalso. apply Hneq. symmetry. by apply encode_inv_Some_nat.
Qed.
Lemma is_seriesC_singleton (a : A) v :
is_seriesC (λ (n : A), if bool_decide (n = a) then v else 0) v.
Proof. apply is_seriesC_singleton_dependent. Qed.
Lemma ex_seriesC_singleton_dependent (a : A) v :
ex_seriesC (λ (n : A), if bool_decide (n = a) then v n else 0).
Proof. eexists. eapply is_seriesC_singleton_dependent. Qed.
Lemma ex_seriesC_singleton (a : A) v :
ex_seriesC (λ (n : A), if bool_decide (n = a) then v else 0).
Proof. eexists. eapply is_seriesC_singleton. Qed.
Lemma SeriesC_singleton_dependent (a : A) v :
SeriesC (λ n, if bool_decide (n = a) then v n else 0) = v a.
Proof. apply is_series_unique, is_seriesC_singleton_dependent. Qed.
Lemma SeriesC_singleton (a : A) v :
SeriesC (λ n, if bool_decide (n = a) then v else 0) = v.
Proof. apply is_series_unique, is_seriesC_singleton. Qed.
Lemma SeriesC_subset g f {_:∀ a, Decision (g a)}:
(∀ (a:A), (¬ g a) -> f a = 0)->
SeriesC f = SeriesC (λ a, if bool_decide (g a) then f a else 0).
Proof.
intros H1.
apply SeriesC_ext.
intros. case_bool_decide; first done.
naive_solver.
Qed.
Lemma is_seriesC_singleton_inj (b : B) (f : A → B) v `{Inj A B (=) (=) f} :
(∃ a, f a = b) →
is_seriesC (λ (a : A), if bool_decide (f a = b) then v else 0) v.
Proof.
intros (a & Ha).
rewrite /is_seriesC.
eapply is_series_ext; [|apply (is_series_singleton (encode_nat a))].
intros n =>/=. rewrite /countable_sum.
case_bool_decide as Hneq=>/=; subst.
- rewrite (encode_inv_encode_nat a) //= bool_decide_eq_true_2 //.
- destruct (encode_inv_nat _) eqn:Heq=>//=.
case_bool_decide; [|done]; subst.
exfalso.
specialize (H1 a0 a H2); simplify_eq.
apply Hneq. symmetry. by apply encode_inv_Some_nat.
Qed.
Lemma ex_seriesC_singleton_inj (b : B) (f : A → B) v `{Inj A B (=) (=) f} :
(∃ a, f a = b) →
ex_seriesC (λ (a : A), if bool_decide (f a = b) then v else 0).
Proof.
eexists. apply is_seriesC_singleton_inj; auto.
Qed.
Lemma SeriesC_singleton_inj (b : B) (f : A → B) v `{Inj A B (=) (=) f} :
(∃ a, f a = b) →
SeriesC (λ (a : A), if bool_decide (f a = b) then v else 0) = v.
Proof.
intros. apply is_seriesC_unique, is_seriesC_singleton_inj; auto.
Qed.
Lemma SeriesC_ge_elem (f : A → R) (a : A) :
(∀ x, 0 <= f x) →
ex_seriesC f →
f a <= SeriesC f.
Proof.
intros Hf Hex.
rewrite -(SeriesC_singleton a (f a)).
apply SeriesC_le; [|done].
intros a'. specialize (Hf a').
case_bool_decide; simplify_eq; lra.
Qed.
Lemma ex_seriesC_singleton' (a : A) v :
ex_seriesC (λ (n : A), if bool_decide (a = n) then v else 0).
Proof.
apply (ex_seriesC_ext (λ n : A, if bool_decide (n = a) then v else 0)
(λ n : A, if bool_decide (a = n) then v else 0)).
+ intro a'; rewrite (bool_decide_ext (a = a') (a' = a)); done.
+ apply ex_seriesC_singleton.
Qed.
Lemma SeriesC_singleton' (a : A) v :
SeriesC (λ n, if bool_decide (a = n) then v else 0) = v.
Proof.
rewrite (SeriesC_ext (λ n : A, if bool_decide (a = n) then v else 0)
(λ n : A, if bool_decide (n = a) then v else 0)).
+ apply SeriesC_singleton.
+ intro a'; rewrite (bool_decide_ext (a = a') (a' = a)); done.
Qed.
Lemma ex_seriesC_list (l : list A) (f : A -> R):
ex_seriesC (λ (a : A), if bool_decide(a ∈ l) then f a else 0).
Proof.
induction l.
{ eapply ex_seriesC_ext; last apply ex_seriesC_0.
intros; done.
}
destruct (decide(a ∈ l)).
{ eapply ex_seriesC_ext; last done.
intros.
simpl.
erewrite bool_decide_ext; first done.
set_solver.
}
eapply ex_seriesC_ext; last apply ex_seriesC_plus.
2:{ apply IHl. }
2:{ eapply (ex_seriesC_singleton _ (f a)). }
intros x.
simpl.
repeat case_bool_decide; try set_solver.
all: try (by subst).
all: try lra.
- subst. apply Rplus_0_l.
- subst. set_solver.
Qed.
Lemma SeriesC_list (l:list A) f:
NoDup l -> SeriesC (λ (a : A), if bool_decide(a ∈ l) then f a else 0) =
foldr (Rplus ∘ f) 0%R l.
Proof.
induction l as [|a l IHl].
- intros. simpl. apply SeriesC_0; naive_solver.
- intro Hnd. simpl. rewrite -IHl; last first.
{ inversion Hnd. done. }
erewrite <-(SeriesC_singleton_dependent _ ) at 1.
erewrite <-SeriesC_plus; last first.
{ apply ex_seriesC_list. }
{ apply ex_seriesC_singleton_dependent. }
apply SeriesC_ext.
intros.
rewrite NoDup_cons in Hnd.
destruct Hnd as [H1 H2].
repeat case_bool_decide; try lra; set_solver.
Qed.
Lemma SeriesC_list_1 (l:list A):
NoDup l -> SeriesC (λ (a : A), if bool_decide(a ∈ l) then 1 else 0) = length l.
Proof.
intros.
rewrite SeriesC_list; last done.
clear.
induction l; first (simpl;lra).
simpl. rewrite -/(INR (S _)). rewrite S_INR.
rewrite IHl. lra.
Qed.
Lemma SeriesC_list_2 (l:list A) r:
NoDup l -> SeriesC (λ (a : A), if bool_decide(a ∈ l) then r else 0) = r * length l.
Proof.
intros.
rewrite SeriesC_list; last done.
clear.
induction l; first (simpl;lra).
simpl. rewrite -/(INR (S _)). rewrite S_INR.
rewrite IHl. lra.
Qed.
Lemma ex_seriesC_finite_from_option (l : list A) (f : B -> R) (g : A -> option B):
(∀ a : A, is_Some (g a) <-> a ∈ l) ->
ex_seriesC (λ (a : A), from_option f 0%R (g a)).
Proof.
intros Hl.
eapply ex_seriesC_ext; last apply (ex_seriesC_list l).
intros a.
simpl.
case_bool_decide as H1; first done.
destruct (g a) eqn:K.
{ exfalso. apply H1. apply Hl. done. }
done.
Qed.
Lemma ex_seriesC_from_option h f:
(∀ n, 0 <= f n) ->
(∀ (n1 n2:B) (m : A), h n1 = Some m → h n2 = Some m → n1 = n2) ->
ex_seriesC f → ex_seriesC (λ a : B, from_option f 0 (h a)).
Proof.
intros Hpos Hinj H1.
apply ex_seriesC_ex_series.
apply ex_pos_bounded_series.
{ intros n.
rewrite /countable_sum.
rewrite /from_option.
repeat case_match; real_solver. }
exists (SeriesC f).
intros n.
assert (∃ l : list _,
(∀ m, m∈l->(∃ k a, (k<=n)%nat /\ (@encode_inv_nat B _ _ k%nat) = Some a /\
h a = Some m)) /\
sum_n (countable_sum (λ a : B, from_option f 0 (h a))) n <=
SeriesC (λ a, if bool_decide(a ∈ l) then f a else 0)
) as H'; last first.
{ destruct H' as [?[??]].
etrans; first exact.
apply SeriesC_le'; try done.
- intros. case_bool_decide; naive_solver.
- apply ex_seriesC_list.
}
induction n.
+ destruct (@encode_inv_nat B _ _ 0%nat) as [a|]eqn:Ha.
* destruct (h a) as [b|] eqn : Hb.
-- exists [b]. split.
++ intros. exists 0%nat, a.
repeat split; try lia; try done.
rewrite Hb. f_equal. set_solver.
++ rewrite sum_O. rewrite /countable_sum.
rewrite Ha. simpl. rewrite Hb. simpl.
erewrite SeriesC_ext.
** erewrite SeriesC_singleton_dependent. done.
** intro. simpl.
repeat case_bool_decide; set_solver.
-- exists []. split.
++ intros; set_solver.
++ rewrite sum_O. rewrite /countable_sum.
rewrite Ha. simpl. rewrite Hb. simpl.
rewrite SeriesC_0; intros; lra.
* exists []. split.
++ intros; set_solver.
++ rewrite sum_O. rewrite /countable_sum.
rewrite Ha. simpl.
rewrite SeriesC_0; intros; lra.
+ assert (0<=n)%nat as Hge0.
* lia.
* destruct IHn as [l[H2 H3]].
destruct (@encode_inv_nat B _ _ (S n)%nat) as [a|] eqn:Ha.
-- destruct (h a) as [b|] eqn : Hb.
++ exists (b::l). split.
** intros. set_unfold.
destruct H4; subst.
--- exists (S n), a. split; try lia. split; done.
--- specialize (H2 m H4).
destruct H2 as [?[?[?[??]]]].
exists x, x0. split; try lia. by split.
** rewrite sum_Sn. rewrite {2}/countable_sum.
rewrite Ha. simpl. rewrite Hb. simpl.
rewrite (SeriesC_ext _ (λ x, (if bool_decide (x=b) then f b else 0) +
if bool_decide (x∈l) then f x else 0
)); last first.
{ intros.
case_bool_decide.
- set_unfold. destruct H4.
+ case_bool_decide; last done.
case_bool_decide.
* subst. specialize (H2 b H6).
destruct H2 as [?[?[?[??]]]].
rewrite -H7 in Hb.
assert (a = x0).
{ eapply Hinj; try done. rewrite Hb. done. }
subst. exfalso.
rewrite -H4 in Ha. assert (x≠ (S n)) by lia.
apply H8. by eapply encode_inv_nat_some_inj.
* subst. lra.
+ case_bool_decide.
{ subst. specialize (H2 b H4) as [?[?[?[??]]]].
assert (x ≠ S n) by lia.
exfalso. apply H7. eapply encode_inv_nat_some_inj; try done.
rewrite Ha H5. f_equal.
by eapply Hinj.
}
case_bool_decide; try done. lra.
- repeat case_bool_decide.
+ set_solver.
+ set_solver.
+ set_solver.
+ lra.
}
rewrite SeriesC_plus; last first.
{ by apply ex_seriesC_list. }
{ by apply ex_seriesC_singleton. }
rewrite Rplus_comm. rewrite SeriesC_singleton.
trans ((sum_n (countable_sum (λ a0 : B, from_option f 0 (h a0))) n) + f b); try lra.
done.
++ exists l. split.
** intros. specialize (H2 _ H4) as [?[?[?[??]]]].
exists x, x0. repeat split; try done. lia.
** rewrite sum_Sn. rewrite {2}/countable_sum. rewrite Ha. simpl.
rewrite Hb. simpl. etrans; last exact.
by rewrite plus_zero_r.
-- exists l. split.
++ intros. specialize (H2 _ H4) as [?[?[?[??]]]].
exists x, x0. repeat split; try done. lia.
++ rewrite sum_Sn. rewrite {2}/countable_sum. rewrite Ha. simpl.
etrans; last exact.
by rewrite plus_zero_r.
Qed.
Lemma is_seriesC_filter_pos f v P `{∀ x, Decision (P x)} :
(∀ n, 0 <= f n) →
is_seriesC f v →
ex_seriesC (λ n, if bool_decide (P n) then f n else 0).
Proof.
intros Hge Hconv.
apply: ex_seriesC_le; last by (exists v; eauto).
intros n. rewrite /norm /= /abs.
specialize (Hge n). case_bool_decide; lra.
Qed.
Lemma is_seriesC_filter_impl f v P Q `{∀ x, Decision (P x), ∀ x, Decision (Q x)} :
(∀ n, 0 <= f n) →
is_seriesC (λ n, if bool_decide (P n) then f n else 0) v →
(∀ n, Q n → P n) →
ex_seriesC (λ n, if bool_decide (Q n) then f n else 0).
Proof.
intros Hge Hconv Himp. apply ex_seriesC_Rabs.
apply: ex_seriesC_le; last by (exists v; eauto).
intros n. rewrite /norm//=/abs//=.
specialize (Hge n). specialize (Himp n).
do 2 case_bool_decide; try (rewrite Rabs_right; auto; lra).
tauto.
Qed.
Lemma ex_seriesC_filter_impl f P Q `{∀ x, Decision (P x), ∀ x, Decision (Q x)} :
(∀ n, 0 <= f n) →
ex_seriesC (λ n, if bool_decide (P n) then f n else 0) →
(∀ n, Q n → P n) →
ex_seriesC (λ n, if bool_decide (Q n) then f n else 0).
Proof. intros ? [? ?] ?. eapply is_seriesC_filter_impl; eauto. Qed.
Lemma ex_seriesC_filter_pos f P `{∀ x, Decision (P x)} :
(∀ n, 0 <= f n) →
ex_seriesC f →
ex_seriesC (λ n, if bool_decide (P n) then f n else 0).
Proof. intros ? [v His]. by eapply is_seriesC_filter_pos. Qed.
Lemma SeriesC_filter_leq f P `{∀ x, Decision (P x)} :
(∀ n, 0 <= f n) →
ex_seriesC f →
SeriesC (λ n, if bool_decide (P n) then f n else 0) <= SeriesC f.
Proof. intros ? ?.
apply SeriesC_le; auto.
intro n; case_bool_decide; simpl; split; auto; lra.
Qed.
(* TODO: make a SeriesC_minus lemma and cleanup proof *)
Lemma is_seriesC_filter_union f v P Q `{∀ x, Decision (P x), ∀ x, Decision (Q x)} :
(∀ n, 0 <= f n) →
is_seriesC (λ n, if bool_decide (P n ∨ Q n) then f n else 0) v →
SeriesC (λ n, if bool_decide (P n) then f n else 0) +
SeriesC (λ n, if bool_decide (Q n) then f n else 0) -
SeriesC (λ n, if bool_decide (P n ∧ Q n) then f n else 0) = v.
Proof.
intros Hge Hexists.
rewrite -SeriesC_plus; last first.
{apply (is_seriesC_filter_impl _ _ _ _ Hge Hexists); eauto. }
{ apply (is_seriesC_filter_impl _ _ _ _ Hge Hexists); eauto. }
rewrite -SeriesC_minus.
- rewrite -(is_seriesC_unique _ v Hexists).
apply SeriesC_ext => n.
do 2 repeat case_bool_decide=>//=; try tauto; lra.
- apply: (ex_seriesC_le _ (λ a, scal 2 (if bool_decide (P a ∨ Q a) then f a else 0))).
+ intros a. rewrite /scal /= /mult /=.
specialize (Hge a). do 3 case_bool_decide => /=; try (lra || tauto).
+ eexists. by eapply is_seriesC_scal_l.
- eapply (is_seriesC_filter_impl _ _ _ _ Hge Hexists). intros ? []; auto.
Qed.
Lemma ex_seriesC_split_elem f (a0 : A) :
ex_seriesC (λ a, if bool_decide (a ≠ a0) then f a else 0) → ex_seriesC f.
Proof.
intros Ha0.
eapply (ex_seriesC_ext (λ a, (λ a, if bool_decide (a = a0) then f a else 0) a +
(λ a, if bool_decide (a ≠ a0) then f a else 0) a)).
{ intros a. case_bool_decide; simplify_eq.
- rewrite bool_decide_eq_false_2; [lra|auto].
- rewrite bool_decide_eq_true_2 //. lra. }
eapply ex_seriesC_plus; [|done].
eapply ex_seriesC_ext; [|eapply (ex_seriesC_singleton a0 (f a0))].
intros a. simpl. by case_bool_decide; simplify_eq.
Qed.
Lemma SeriesC_split_elem f (a0 : A) :
(∀ a, 0 <= f a) → (* TODO: this requirements should not be necessary? *)
ex_seriesC f →
SeriesC f = SeriesC (λ a, if bool_decide (a = a0) then f a else 0) +
SeriesC (λ a, if bool_decide (a ≠ a0) then f a else 0).
Proof.
intros Hle Hex.
erewrite SeriesC_ext.
{ eapply SeriesC_plus; [by eapply ex_seriesC_filter_pos|].
eapply (ex_seriesC_le _ f); [|done].
intros a'. case_bool_decide; split; (done || lra). }
intros a. simpl. case_bool_decide as Heq.
- rewrite bool_decide_eq_false_2; [lra|]. eauto.
- rewrite bool_decide_eq_true_2 //. lra.
Qed.
Lemma SeriesC_split_pred f (P : A -> bool) :
(∀ a, 0 <= f a) →
ex_seriesC f →
SeriesC f = SeriesC (λ a, if P a then f a else 0) +
SeriesC (λ a, if P a then 0 else f a).
Proof.
intros Hle Hex.
rewrite -SeriesC_plus.
- apply SeriesC_ext; intro.
destruct (P _); lra.
- apply (ex_seriesC_le _ f); auto.
intro; real_solver.
- apply (ex_seriesC_le _ f); auto.
intro; real_solver.
Qed.
Lemma ex_seriesC_filter_bool_pos f (P : A → bool) :
(∀ a, 0 <= f a) →
ex_seriesC f →
ex_seriesC (λ a, if P a then f a else 0).
Proof.
intros Hpos Hex.
apply (ex_seriesC_le _ f); auto.
intro n; specialize (Hpos n); destruct (P n); lra.
Qed.
Lemma SeriesC_pos (f : A → R) a :
(∀ a, 0 <= f a) →
ex_seriesC f →
f a > 0 →
SeriesC f > 0.
Proof.
intros Hpos Hex Ha.
rewrite (SeriesC_split_elem _ a); [|done|done].
rewrite SeriesC_singleton_dependent.
assert (0 <= SeriesC (λ a', if bool_decide (a' ≠ a) then f a' else 0)); [|lra].
eapply SeriesC_ge_0' => a'.
by case_bool_decide.
Qed.
End filter.
Lemma ex_seriesC_list_length `{Finite A} (f:list A -> R) num:
(forall x, (0≠f x)%R -> length x = num) ->
ex_seriesC f.
Proof.
intros.
eapply (ex_seriesC_ext (λ x, if bool_decide(x∈enum_uniform_list num) then f x else 0))%R.
- intros n.
case_bool_decide as K; first done.
destruct (Req_dec (f n) 0); first done.
exfalso.
apply K. apply elem_of_enum_uniform_list.
naive_solver.
- apply ex_seriesC_list.
Qed.
Lemma SeriesC_Series_nat (f : nat → R) :
SeriesC f = Series f.
Proof.
rewrite /SeriesC.
erewrite Series_ext; [done|].
rewrite /countable_sum /from_option /= => n.
case_match eqn:He.
- by apply encode_inv_nat_Some_inj in He as ->.
- by apply encode_inv_nat_None in He.
Qed.
Lemma is_seriesC_is_series_nat (f : nat → R) v :
is_series f v → is_seriesC f v.
Proof.
intros Hf.
eapply is_series_ext; [|done]=> n.
rewrite /is_seriesC /countable_sum /from_option /=.
case_match eqn:He.
- by apply encode_inv_nat_Some_inj in He as ->.
- by apply encode_inv_nat_None in He.
Qed.
Lemma SeriesC_bool (f : bool → R) :
SeriesC f = f true + f false.
Proof.
rewrite (SeriesC_ext _ (λ b, (if bool_decide (b = true) then f true else 0) +
if bool_decide (b = false) then f false else 0)).
{ rewrite SeriesC_plus; [|eapply ex_seriesC_singleton..].
rewrite 2!SeriesC_singleton //. }
intros []; simpl; lra.
Qed.
Lemma SeriesC_fin2 (f : fin 2 → R) :
SeriesC f = f 0%fin + f 1%fin.
Proof.
rewrite (SeriesC_ext _ (λ b, (if bool_decide (b = 0%fin) then f 0%fin else 0) +
if bool_decide (b = 1%fin) then f 1%fin else 0)).
{ rewrite SeriesC_plus; [|eapply ex_seriesC_singleton..].
rewrite 2!SeriesC_singleton //. }
intros n; inv_fin n; [simpl; lra|].
intros n; inv_fin n; [simpl; lra|].
intros n; inv_fin n.
Qed.
Lemma ex_seriesC_nat_bounded (f : nat -> R) (N : nat) :
ex_seriesC (λ (n : nat), if bool_decide ((n <= N)%nat) then f n else 0).
Proof.
induction N.
- apply (ex_seriesC_ext (λ n : nat, if bool_decide (n = 0%nat) then f 0%nat else 0)); [ | apply ex_seriesC_singleton ].
intro; do 2 case_bool_decide; simplify_eq; try lia; try lra.
- eapply (ex_seriesC_ext); last first.
+ apply ex_seriesC_plus; [ apply IHN | ].
apply (ex_seriesC_singleton (S N) (f (S N))).
+ intros; do 3 case_bool_decide; simplify_eq; try lia; try lra.
Qed.
Lemma ex_seriesC_nat_bounded_Zle (f : nat -> R) (z : Z) :
ex_seriesC (λ (n : nat), if bool_decide (Z.of_nat n <= z)%Z then f n else 0).
Proof.
destruct (Z_lt_ge_dec z 0) as [H|H].
- eapply ex_seriesC_ext; [ | apply ex_seriesC_0].
intro n.
rewrite bool_decide_eq_false_2; auto.
lia.
- eapply ex_seriesC_ext; [ | apply (ex_seriesC_nat_bounded f (Z.to_nat z))].
intro n.
case_bool_decide.
+ rewrite bool_decide_eq_true_2; auto.
zify.
lia.
+ rewrite bool_decide_eq_false_2; auto.
zify.
lia.
Qed.
Lemma ex_seriesC_nat_bounded_Rle (f : nat -> R) (N : nat) :
ex_seriesC (λ (n : nat), if bool_decide (n <= N) then f n else 0).
Proof.
eapply ex_seriesC_ext; [ | apply (ex_seriesC_nat_bounded f N)].
intro.
case_bool_decide.
- rewrite bool_decide_eq_true_2; auto.
by apply INR_le.
- rewrite bool_decide_eq_false_2; auto.
apply Nat.lt_nge.
apply INR_lt.
lra.
Qed.
Lemma ex_seriesC_nat_eventually_zero (f : nat -> R) (N : nat) (M : nat) :
(forall n : nat, M <= n -> f n = 0) ->
ex_seriesC f.
Proof.
intros H.
eapply ex_seriesC_ext; last first.
{ eapply (ex_seriesC_nat_bounded_Rle f M). }
intros n.
simpl; case_bool_decide; auto.
rewrite H //.
lra.
Qed.
Lemma SeriesC_nat_bounded (f : nat -> R) (N : nat) :
SeriesC (λ (n : nat), if bool_decide ((n <= N)%nat) then f n else 0) = sum_n f N.
Proof.
induction N.
- rewrite sum_O.
rewrite (SeriesC_ext _ (λ n : nat, if bool_decide (n = 0%nat) then f 0%nat else 0)).
{
apply SeriesC_singleton.
}
intros n.
pose proof (pos_INR n).
case_bool_decide as H2; case_bool_decide as H3;
simplify_eq; auto.
+ inversion H2; done.
+ destruct H2; auto.
- rewrite sum_Sn //.
rewrite -IHN.
rewrite -(SeriesC_singleton (S N) (f (S N))).
rewrite /plus/=.
rewrite -SeriesC_plus.
+ apply SeriesC_ext.
intro.
do 3 case_bool_decide; simplify_eq; try lia; try lra.
+ apply ex_seriesC_nat_bounded.
+ apply ex_seriesC_singleton.
Qed.
Lemma SeriesC_split_first (f : nat -> R) :
(∀ n, 0 <= f n) → (* TODO: this requirements should not be necessary? *)
ex_seriesC f →
SeriesC f = (f 0%nat) + SeriesC (λ n, f (S n)).
Proof.
intros Hle Hex.
rewrite (SeriesC_split_elem f 0%nat); auto.
rewrite SeriesC_singleton_dependent.
f_equal; auto.
rewrite SeriesC_nat.
rewrite SeriesC_nat.
rewrite Series_incr_1_aux.
- apply Series_ext.
intro n.
rewrite bool_decide_eq_true_2; [done|lia].
- rewrite bool_decide_eq_false_2; [done|lia].
Qed.
Section strict.
Context `{Countable A}.
Implicit Types f g : A → R.
Lemma SeriesC_lt f g :
(∀ n, 0 <= f n <= g n) →
(∃ m, f m < g m) →
ex_seriesC g →
SeriesC f < SeriesC g.
Proof.
intros Hle Hlt Hg.
assert (ex_seriesC f) as Hf.
{ apply (ex_seriesC_le f g); auto. }
destruct Hlt as (m & Hlt).
assert (g m - f m > 0) as Hgtz ; try lra.
set (d := g m - f m).
set (h := (λ n, if bool_decide (n = m) then d else 0) ).
assert (ex_seriesC h) as Hh.
{ apply ex_seriesC_singleton. }
assert (SeriesC h > 0) as Hhgt.
{ rewrite SeriesC_singleton; auto. }
assert (SeriesC f + SeriesC h <= SeriesC g); try lra.
rewrite <- SeriesC_plus; auto.
apply SeriesC_le; auto.
intro n.
specialize (Hle n) as (Hle1 & Hle2).
rewrite /h /d.
case_bool_decide as Hnm; split; try lra.
rewrite Hnm; lra.
Qed.
Lemma SeriesC_const0 f :
(∀ n, 0 <= f n) →
is_seriesC f 0 →
(∀ n, f n = 0).
Proof.
intros Hf Hz n.
pose proof (is_seriesC_unique _ _ Hz) as Hz'.
pose proof (Rtotal_order (f n) 0) as Htri.
destruct Htri as [H1 | [H2 | H3]] ; try lra.
- specialize (Hf n); lra.
- assert (0 < SeriesC f); try lra.
assert (SeriesC (λ _ : A, 0) = 0) as H4.
{ apply SeriesC_0; auto. }
destruct H4.
eapply (SeriesC_lt (λ n, 0) f).
+ intro n0; specialize (Hf n0); lra.
+ exists n; lra.
+ exists 0; done.
Qed.
Lemma SeriesC_gtz_ex f :
(∀ n, 0 <= f n) →
SeriesC f > 0 →
∃ n, f n > 0.
Proof.
intro Hf.
eapply contrapositive. intros Hna.
assert (∀ a, f a = 0) as Hz.
{ intros a.
pose proof (not_exists_forall_not _ _ Hna a).
specialize (Hf a); lra. }
apply Rge_not_gt. rewrite SeriesC_0 //.
Qed.
End strict.
Section finite.
Context `{Finite A}.
Lemma ex_seriesC_finite (f : A → R) :
ex_seriesC f.
Proof.
apply ex_series_eventually0.
exists (card A).
intros n Hn.
rewrite /countable_sum /=.
destruct (encode_inv_nat _) as [a|] eqn:Heq=>//=.
pose proof (encode_lt_card a).
rewrite /encode_inv_nat in Heq.
destruct (decode_nat n); simplify_option_eq.
lia.
Qed.
Lemma SeriesC_finite_foldr (f : A → R) :
SeriesC f = foldr (Rplus ∘ f) 0%R (enum A).
Proof.
rewrite /SeriesC /countable_sum.
setoid_rewrite encode_inv_nat_finite.
generalize (enum A).
induction l.
{ apply Series_0. eauto. }
rewrite Series_incr_1.
{ rewrite IHl //. }
eapply ex_series_ext;
[|eapply ex_seriesC_nat, (ex_seriesC_nat_bounded _ (length l + 1))].
intros n => /=.
case_bool_decide; [done|].
rewrite lookup_ge_None_2 //=. lia.
Qed.
Lemma SeriesC_finite_mass v :
SeriesC (λ _ : A, v) = card A * v.
Proof.
rewrite /SeriesC.
rewrite -(Series_ext (λ n, if bool_decide (n < card A)%nat then v else 0)); last first.
{ intros n. rewrite /countable_sum /=.
case_bool_decide as Hn; simpl.
- destruct (encode_inv_nat) eqn:Heq; [done|]; simpl.
destruct (encode_inv_decode _ Hn) as (a & Hinv & He).
simplify_option_eq.
- destruct (encode_inv_nat) eqn:Heq; [|done]; simpl.
rewrite encode_inv_decode_ge in Heq; [done|lia]. }
apply (SeriesC_leq (card A) v).
Qed.
Lemma SeriesC_finite_bound (f : A → R) v :
(∀ a, 0 <= f a <= v) →
SeriesC f <= card A * v.
Proof.
intros Hf.
rewrite -SeriesC_finite_mass.
apply SeriesC_le ; [done|].
apply ex_seriesC_finite.
Qed.
#[local] Fixpoint Rmax_seq (f : nat -> R) n :=
match n with
| 0 => f 0%nat
| S m => Rmax (f (S m)) (Rmax_seq f m)
end.
#[local] Lemma le_Rmax_seq (f : nat -> R) n m :
(m ≤ n) ->
(f m <= Rmax_seq f n)%R.
Proof.
intros Hleq.
induction Hleq.
- destruct m; simpl; [lra|].
apply Rmax_l.
- simpl.
etrans; eauto.
apply Rmax_r.
Qed.
Lemma fin_function_bounded (N : nat) (f : fin N -> R) :
exists r, forall n, (f n <= r)%R.
Proof.
induction N as [|M].
- exists 0.
intros.
by apply Fin.case0.
- set (g := (λ (n : nat), f (fin.fin_force _ n))).
exists (Rmax_seq g M).
intros n.
pose proof (fin_to_nat_lt n).
transitivity (g n).
+ rewrite /g /=.
right.
f_equal.
apply fin_to_nat_inj.
rewrite fin.fin_force_to_nat_le; lia.
+ apply le_Rmax_seq; lia.
Qed.
End finite.
(* We might need the results below to reason about uniform distributions *)
Definition extend_fin_to_R {n : nat} (f: fin n -> R) : (nat->R) :=
fun x =>
match le_lt_dec n x with
| left _ => 0%R
| right h => f (nat_to_fin h)
end.
Local Lemma foldr_ext_strong {A B} (f1 f2 : B → A → A) x1 l1 :
(∀ b a, b∈ l1 -> f1 b a = f2 b a) → foldr f1 x1 l1 = foldr f2 x1 l1.
Proof. revert x1.
induction l1.
- naive_solver.
- intros. simpl. rewrite IHl1.
+ rewrite H; [done|set_solver].
+ intros. set_unfold. naive_solver.
Qed.
Lemma SeriesC_fin_sum {n : nat} (f : fin (S n) -> R) :
SeriesC f = sum_n (extend_fin_to_R f) n.
Proof.
rewrite SeriesC_finite_foldr.
rewrite <- seq_enum_fin.
revert f. induction n.
- naive_solver.
- intros. rewrite sum_n_shift'. rewrite Rplus_comm.
rewrite -cons_seq fmap_cons foldr_cons.
assert (forall x y, (Rplus ∘ f) x y = f x + y) as -> by naive_solver.
f_equal. rewrite -fmap_S_seq -list_fmap_compose.
replace (foldr (Rplus ∘ f) 0
((λ x : nat, match le_lt_dec (S (S n)) x with
| left _ => 0%fin
| right h => nat_to_fin h
end) ∘ S <$> seq 0 (S n))) with
(foldr (Rplus ∘ (λ x, f (FS x))) 0
((λ x : nat, match le_lt_dec (S n) x with
| left _ => 0%fin
| right h => nat_to_fin h
end) <$> seq 0 (S n))).
+ rewrite IHn.
apply sum_n_ext_loc.
clear.
intros x Hx.
rewrite /extend_fin_to_R.
repeat case_match; try lia.
f_equal. apply fin_to_nat_inj.
simpl. by rewrite !fin_to_nat_to_fin.
+ clear.
rewrite !foldr_fmap. apply foldr_ext_strong.
intros b a. rewrite elem_of_seq.
intros Hb. simpl. repeat case_match; try lia.
* do 3 f_equal.
* do 3 f_equal. apply fin_to_nat_inj. simpl. by rewrite !fin_to_nat_to_fin.
Qed.
Lemma SeriesC_nat_bounded_fin f N:
SeriesC (λ n : nat, if bool_decide (n ≤ N) then f n else 0) =
SeriesC (λ n:(fin (S N)), f (fin_to_nat n)).
Proof.
rewrite SeriesC_fin_sum.
rewrite SeriesC_nat_bounded.
apply sum_n_ext_loc.
intros n ?.
rewrite /extend_fin_to_R.
case_match; first lia.
by rewrite fin_to_nat_to_fin.
Qed.
Lemma SeriesC_nat_bounded_to_foldr (f : nat -> R) (N : nat) :
SeriesC (λ (n : nat), if bool_decide ((n <= N)%nat) then f n else 0) = foldr (Rplus ∘ f ∘ fin_to_nat) 0%R (enum (fin (S N))).
Proof.
rewrite SeriesC_nat_bounded_fin.
by rewrite SeriesC_finite_foldr.
Qed.
Lemma SeriesC_nat_bounded_to_foldr' (f : nat -> R) (N : nat) :
SeriesC (λ (n : nat), if bool_decide ((n <= N)%nat) then f n else 0) = foldr Rplus 0%R ( f <$> seq 0 (S N)).
Proof.
rewrite SeriesC_nat_bounded_fin.
rewrite -enum_fin_seq.
rewrite SeriesC_finite_foldr.
assert (forall {A B} (l : list A) (h2 : B -> R) (h1 : A -> B),
foldr (Rplus ∘ h2 ∘ h1 ) 0 l = foldr (Rplus ∘ h2) 0 (h1 <$> l)) as Haux.
{
induction l.
- intros l.
simpl. done.
- intros h1 h2.
simpl.
f_equal.
auto.
}
rewrite -Haux.
rewrite -Haux.
apply foldr_ext; auto.
Qed.
Results about positive (non-negative) series
Section positive.
Context `{Countable A}.
Implicit Types f g : A → R.
Lemma limC_is_sup (h: A → R) r :
(∀ n, 0 <= h n) →
is_seriesC h r →
is_sup_seq (sumC_n h) (Rbar.Finite r).
Proof.
intros Hge Hs.
rewrite /is_seriesC in Hs.
eapply (lim_is_sup (countable_sum h) r); auto.
intro n. rewrite /countable_sum /from_option; edestruct (@encode_inv_nat A _ H n); auto ; lra.
Qed.
Lemma sup_is_limC (h: A → R) r :
(∀ n, 0 <= h n) →
is_sup_seq (sumC_n h) (Rbar.Finite r) →
is_seriesC h r.
Proof.
intros Hge Hsup.
rewrite /is_seriesC.
eapply (sup_is_lim); auto.
intro n; rewrite /countable_sum /from_option; destruct (encode_inv_nat _); auto; lra.
Qed.
End positive.
Section bounds.
Context `{Countable A}.
Definition is_lubC (h: A → R) (u : Rbar) :=
(∀ a, Rbar_le (h a) u) /\ (∀ u', (∀ a, Rbar_le (h a) u') → Rbar_le u u').
Lemma ex_lubC (h : A → R) :
{u | is_lubC h u}.
Proof.
destruct (Lub_Rbar_correct ((λ r : R, ∃ a0 : A, h a0 = r))) as [H1 H2].
exists (Lub_Rbar (λ (r : R), exists a, h a = r)); split.
- intro a.
apply H1; eauto.
- intros u' Hu'.
apply H2; auto.
rewrite /is_ub_Rbar.
intros x (a & <-); auto.
Qed.
Definition LubC (h : A → R) := proj1_sig (ex_lubC h).
Lemma LubC_correct (h : A → R) :
is_lubC h (LubC h).
Proof.
rewrite /LubC ; by case: ex_lubC => l /= Hl.
Qed.
Lemma seriesC_le_lub (h : A → R) :
ex_seriesC h →
is_finite (LubC h) →
ex_seriesC (λ a : A, real (LubC h)) →
SeriesC h <= SeriesC (λ a : A, real (LubC h)).
Proof.
intros Hex Hfin Hex2.
apply SeriesC_le'; auto.
intro n.
destruct (LubC_correct h) as [H1 H2].
apply rbar_le_finite; auto.
Qed.
Definition is_glbC (h: A → R) (l : Rbar) :=
(∀ a, Rbar_le l (h a) ) ∧ (∀ l', (∀ a, Rbar_le l' (h a)) → Rbar_le l' l).
Lemma ex_glbC (h : A → R) :
{u | is_glbC h u}.
Proof.
destruct (Glb_Rbar_correct ((λ r : R, ∃ a0 : A, h a0 = r))) as [H1 H2].
exists (Glb_Rbar (λ (r : R), exists a, h a = r)); split.
- intro a.
apply H1; eauto.
- intros u' Hu'.
apply H2; auto.
rewrite /is_lb_Rbar.
intros x (a & <-); auto.
Qed.
Definition GlbC (h : A → R) := proj1_sig (ex_glbC h).
Lemma GlbC_correct (h : A → R) :
is_glbC h (GlbC h).
Proof.
rewrite /GlbC ; by case: ex_glbC => l /= Hl.
Qed.
Lemma seriesC_le_glb (h : A → R) :
ex_seriesC h →
is_finite (GlbC h) →
ex_seriesC (λ a : A, real (GlbC h)) →
SeriesC (λ a : A, real (GlbC h)) <= SeriesC h.
Proof.
intros Hex Hfin Hex2.
apply SeriesC_le'; auto.
intro n.
destruct (GlbC_correct h) as [H1 H2].
apply finite_rbar_le; auto.
Qed.
End bounds.
Section fubini.
Context `{Countable A, Countable B}.
(*
The following three lemmas have been proven for
Series, so the only missing part is lifting them
to SeriesC
*)
Lemma fubini_pos_seriesC_ex (h : A * B → R) :
(∀ a b, 0 <= h (a, b)) →
(∀ a, ex_seriesC (λ b, h (a, b))) →
(ex_seriesC (λ a, SeriesC (λ b, h (a, b)))) →
(∀ b, ex_seriesC (λ a, h (a, b))).
Proof.
intros Hpos Hex1 Hex2 b.
set (f := λ '(n, m), countable_sum (λ a, countable_sum (λ b, h (a,b)) m) n).
assert (∀ m, ex_series (λ n, f (n, m))) as H1.
{
apply fubini_pos_series_ex.
- intros n m.
rewrite /f/countable_sum.
destruct (encode_inv_nat n);
destruct (encode_inv_nat m);
simpl; real_solver.
- intro n. rewrite /f {1}/countable_sum.
destruct (encode_inv_nat n); simpl.
+ apply Hex1.
+ exists 0. apply is_series_0; auto.
- rewrite /f/countable_sum/=.
apply ex_seriesC_ex_series_inv in Hex2.
rewrite /SeriesC/countable_sum/= in Hex2.
eapply ex_series_ext; [ | apply Hex2].
intro n; simpl.
destruct (encode_inv_nat n); simpl; auto.
symmetry; apply Series_0; auto.
}
apply ex_seriesC_ex_series.
eapply ex_series_ext; [ | apply (H1 (encode_nat b)) ].
intros; simpl.
apply countable_sum_ext => a.
rewrite /countable_sum encode_inv_encode_nat //.
Qed.
Lemma fubini_pos_seriesC_ex_double (h : A * B → R) :
(∀ a b, 0 <= h (a, b)) →
(∀ a, ex_seriesC (λ b, h (a, b))) →
(ex_seriesC (λ a, SeriesC (λ b, h (a, b)))) →
(ex_seriesC (λ b, SeriesC (λ a, h (a, b)))).
Proof.
intros Hpos Hex1 Hex2.
set (f := λ '(n, m), countable_sum (λ a, countable_sum (λ b, h (a,b)) m) n).
assert (ex_series (λ m, Series (λ n, f (n, m)))) as H1.
{
apply fubini_pos_series_ex_double.
- intros n m.
rewrite /f/countable_sum.
destruct (encode_inv_nat n);
destruct (encode_inv_nat m);
simpl; real_solver.
- intro n. rewrite /f {1}/countable_sum.
destruct (encode_inv_nat n); simpl.
+ apply Hex1.
+ exists 0. apply is_series_0; auto.
- rewrite /f/countable_sum/=.
apply ex_seriesC_ex_series_inv in Hex2.
rewrite /SeriesC/countable_sum/= in Hex2.
eapply ex_series_ext; [ | apply Hex2].
intro n; simpl.
destruct (encode_inv_nat n); simpl; auto.
symmetry; apply Series_0; auto.
}
apply ex_seriesC_ex_series.
eapply ex_series_ext; [ | apply H1 ].
intros; simpl.
rewrite /SeriesC /countable_sum.
destruct (encode_inv_nat n); simpl; auto.
apply Series_0.
intro m.
destruct (encode_inv_nat m); simpl; auto.
Qed.
Lemma fubini_pos_seriesC (h : A * B → R) :
(∀ a b, 0 <= h (a, b)) →
(∀ a, ex_seriesC (λ b, h (a, b))) →
(ex_seriesC (λ a, SeriesC (λ b, h (a, b)))) →
SeriesC (λ b, SeriesC (λ a, h (a, b))) =
SeriesC (λ a, SeriesC (λ b, h (a, b))).
Proof.
intros Hpos Hex1 Hex2.
set (f := λ '(n, m), countable_sum (λ a, countable_sum (λ b, h (a,b)) m) n).
assert (Series (λ m, Series (λ n, f (n, m))) = Series (λ n, Series (λ m, f (n, m)))) as H1.
{
apply fubini_pos_series.
- intros n m.
rewrite /f/countable_sum.
destruct (encode_inv_nat n);
destruct (encode_inv_nat m);
simpl; real_solver.
- intro n. rewrite /f {1}/countable_sum.
destruct (encode_inv_nat n); simpl.
+ apply Hex1.
+ exists 0. apply is_series_0; auto.
- rewrite /f/countable_sum/=.
apply ex_seriesC_ex_series_inv in Hex2.
rewrite /SeriesC/countable_sum/= in Hex2.
eapply ex_series_ext; [ | apply Hex2].
intro n; simpl.
destruct (encode_inv_nat n); simpl; auto.
symmetry; apply Series_0; auto.
}
etrans; [ etrans; [ | exact H1] | ].
- rewrite /f/SeriesC/countable_sum.
apply Series_ext.
intro n.
destruct (encode_inv_nat n); simpl; auto.
symmetry; apply Series_0; auto.
intro m.
destruct (encode_inv_nat m); simpl; auto.
- rewrite /f/SeriesC/countable_sum.
apply Series_ext.
intro n.
destruct (encode_inv_nat n); simpl; auto.
apply Series_0; auto.
Qed.
Lemma fubini_pos_seriesC' (h : A -> B → R) :
(∀ a b, 0 <= h a b) →
(∀ a, ex_seriesC (λ b, h a b)) →
(ex_seriesC (λ a, SeriesC (λ b, h a b))) →
SeriesC (λ b, SeriesC (λ a, h a b)) =
SeriesC (λ a, SeriesC (λ b, h a b)).
Proof.
intros.
pose (h' := λ '(a,b), h a b).
assert (forall a b, h a b = h' (a,b)) as H'.
{ intros. by rewrite /h'. }
setoid_rewrite H'.
apply fubini_pos_seriesC.
all: by setoid_rewrite <-H'.
Qed.
End fubini.
Section mct.
Context `{Countable A}.
Lemma MCT_seriesC (h : nat → A → R) (l : nat → R) (r : R) :
(∀ n a, 0 <= (h n a)) →
(∀ n a, (h n a) <= (h (S n) a)) →
(∀ a, exists s, ∀ n, h n a <= s ) →
(∀ n, is_seriesC (h n) (l n)) →
is_sup_seq l (Rbar.Finite r) →
SeriesC (λ a, Sup_seq (λ n, h n a)) = r.
Proof.
intros Hpos Hle1 Hle2 Hsr Hsup.
set (f := λ n m, countable_sum (λ a, h n a) m).
assert (Series (λ m, Sup_seq (λ n, f n m)) = r ) as H1.
{
apply (MCT_series f l r).
- intros n m.
rewrite /f/countable_sum.
destruct (encode_inv_nat m);
simpl; real_solver.
- intros n m.
rewrite /f/countable_sum.
destruct (encode_inv_nat m);
simpl; real_solver.
- intro n.
rewrite /f/countable_sum.
destruct (encode_inv_nat) as [a | ].
+ destruct (Hle2 a) as [s Hs].
exists s; auto.
+ exists 0; real_solver.
- intro n.
specialize (Hsr n).
eapply is_series_ext; [ | exact Hsr].
intro m.
rewrite /f /countable_sum.
destruct (encode_inv_nat m); simpl; auto.
- auto.
}
rewrite -H1.
apply Series_ext.
intro n.
rewrite /f/countable_sum.
destruct (encode_inv_nat n); simpl; auto.
symmetry.
apply sup_seq_const.
Qed.
Lemma MCT_ex_seriesC (h : nat → A → R) (l : nat → R) (r : R) :
(∀ n a, 0 <= (h n a)) →
(∀ n a, (h n a) <= (h (S n) a)) →
(∀ a, exists s, ∀ n, h n a <= s ) →
(∀ n, is_seriesC (h n) (l n)) →
is_sup_seq l (Rbar.Finite r) →
ex_seriesC (λ a, Sup_seq (λ n, h n a)).
Proof.
intros Hpos Hle1 Hle2 Hsr Hsup.
set (f := λ n m, countable_sum (λ a, h n a) m).
assert (ex_series (λ m, real (Sup_seq (λ n, f n m)))) as H1.
{
apply (MCT_ex_series f l r).
- intros n m.
rewrite /f/countable_sum.
destruct (encode_inv_nat m);
simpl; real_solver.
- intros n m.
rewrite /f/countable_sum.
destruct (encode_inv_nat m);
simpl; real_solver.
- intro n.
rewrite /f/countable_sum.
destruct (encode_inv_nat) as [a | ].
+ destruct (Hle2 a) as [s Hs].
exists s; auto.
+ exists 0; real_solver.
- intro n.
specialize (Hsr n).
eapply is_series_ext; [ | exact Hsr].
intro m.
rewrite /f /countable_sum.
destruct (encode_inv_nat m); simpl; auto.
- auto.
}
eapply ex_series_ext; [ | apply H1].
intro n.
rewrite /f/countable_sum.
destruct (encode_inv_nat n); simpl; auto.
apply sup_seq_const.
Qed.
Lemma SeriesC_Sup_seq_swap (r : R) (l : nat → R) (h : nat → A → R) :
(∀ n a, 0 <= (h n a)) →
(∀ n a, (h n a) <= (h (S n) a)) →
(∀ a, exists s, ∀ n, h n a <= s ) →
(∀ n, is_seriesC (h n) (l n)) →
(∀ n, l n <= r) →
SeriesC (λ a, Sup_seq (λ n, h n a)) = Sup_seq (λ n, SeriesC (h n)).
Proof.
intros ?????.
eapply MCT_seriesC; [done..|].
assert (∀ n, SeriesC (λ a : A, h n a) = l n) as Heq.
{ intros ?. by eapply is_seriesC_unique. }
erewrite Sup_seq_ext; last first.
{ intros n. rewrite Heq //. }
rewrite (Rbar_le_sandwich 0 r).
- apply Sup_seq_correct.
- apply (Sup_seq_minor_le _ _ 0%nat)=>/=.
rewrite -Heq. by apply SeriesC_ge_0'.
- by apply upper_bound_ge_sup=>/=.
Qed.
End mct.
Section double.
Context `{Countable A, Countable B}.
Variable (h : A * B → R).
Variable (POS : ∀ a b, 0 <= h (a, b)).
Definition σprod (n : nat) :=
match @encode_inv_nat (A*B) _ _ n with
| Some (a, b) => (S (encode_nat a), S (encode_nat b))
| None => (O, O)
end.
Definition aprod (mn : nat * nat) :=
match mn with
| (S m, S n) =>
match @encode_inv_nat A _ _ m, @encode_inv_nat B _ _ n with
| Some a, Some b => h (a, b)
| _, _ => 0
end
| _ => 0
end.
Lemma aprod_pos: ∀ m n, 0 <= aprod (m, n).
Proof .
intros m n. rewrite /aprod.
do 4 (case_match; try lra). auto.
Qed.
Lemma σprod_inj n n' :
aprod (σprod n) ≠ 0 → σprod n = σprod n' → n = n'.
Proof.
rewrite /σprod /aprod.
destruct (encode_inv_nat n) as [[a b]|] eqn: Heq1 => /=; [|nra].
destruct (encode_inv_nat (encode_nat a)) as [a'|] eqn: Heq2; [|nra].
destruct (encode_inv_nat (encode_nat b)) as [b'|] eqn: Heq3; [|nra].
intros _.
destruct (encode_inv_nat n') as [[a'' b'']|] eqn:Heq4;
intros [= <-%(inj _) <-%(inj _)].
rewrite encode_inv_encode_nat in Heq2.
rewrite encode_inv_encode_nat in Heq3.
simplify_eq. rewrite -Heq1 in Heq4.
by eapply encode_inv_nat_some_inj.
Qed.
Lemma σprod_cov n : aprod n ≠ 0 → ∃ m, σprod m = n.
Proof.
destruct n as [[] []]=> //=.
case_match eqn:Ha; [|lra].
case_match eqn:Hb; [|lra].
intros _.
exists (encode_nat (a, b)).
rewrite /σprod.
rewrite encode_inv_encode_nat.
erewrite encode_inv_Some_nat; [|done].
erewrite encode_inv_Some_nat; [|done].
done.
Qed.
Lemma aprod_σprod_countable_sum n :
(aprod ∘ σprod) n = countable_sum h n.
Proof.
rewrite /aprod/σprod/countable_sum/=.
destruct (encode_inv_nat n) as [[]|] eqn:Heq; simpl; [|lra].
do 2 rewrite encode_inv_encode_nat.
lra.
Qed.
Lemma ex_series_σprod :
ex_seriesC h → ex_series (aprod ∘ σprod).
Proof.
intros Hex.
apply ex_pos_bounded_series.
+ intros n. simpl. destruct (σprod n). apply aprod_pos.
+ exists (SeriesC h).
apply ex_seriesC_ex_series_inv in Hex.
intro n.
etrans; last first.
* eapply series_pos_partial_le; [|done].
intro m. apply countable_sum_ge_0. by intros [].
* apply sum_n_le => m.
rewrite aprod_σprod_countable_sum //.
Qed.
#[local] Hint Resolve aprod_pos σprod_inj σprod_cov ex_series_σprod : core.
Lemma aprod_double_summable:
ex_seriesC h → double_summable aprod.
Proof. intros Hex. eapply (summable_implies_ds aprod σprod); auto. Qed.
Lemma aprod_S_double_summable :
ex_seriesC h → double_summable (λ '(j, k), aprod (S j, S k)).
Proof.
intros [r Hr]%aprod_double_summable.
rewrite /double_summable.
exists r.
intros n.
erewrite sum_n_ext; last first.
{ intros m. rewrite (sum_n_shift (λ k, aprod (S m, k))) //. }
rewrite sum_n_plus /plus /=.
rewrite (sum_n_shift (λ k, sum_n (λ j, aprod (k, j)) (S n))).
rewrite sum_n_const.
assert (0 <= sum_n (λ j, aprod (0%nat, j)) (S n)) by eapply partial_sum_pos=>//.
specialize (Hr (S n)).
lra.
Qed.
Lemma is_seriesC_prod_row:
ex_seriesC h → is_seriesC h (Series (λ j, Series (λ k, aprod (S j, S k)))).
Proof.
intro Hex.
apply (is_series_ext (aprod ∘ σprod)); [apply aprod_σprod_countable_sum|].
eapply is_series_chain; [apply is_series_double_covering'; auto|].
cut (Series (λ j, Series (λ k, aprod (j, k))) =
(Series (λ j, Series (λ k, aprod (S j, S k))))).
{ intros <-. apply Series_correct. eexists.
eapply (is_series_double_covering aprod σprod); auto. }
rewrite Series_incr_1; last first.
{ eexists. eapply is_series_double_covering; eauto. }
rewrite {1}/aprod Series_0 // Rplus_0_l.
apply Series_ext => n.
rewrite Series_incr_1; last first.
{ apply ex_series_row; [|auto]. by apply aprod_double_summable. }
rewrite {1}/aprod Rplus_0_l => //=.
Qed.
Lemma is_seriesC_prod_column:
ex_seriesC h → is_seriesC h (Series (λ k, Series (λ j, aprod (S j, S k)))).
Proof.
intros Hex.
rewrite -(double_summable_fubini (λ '(j, k), aprod (S j, S k))).
- by apply is_seriesC_prod_row.
- intros []; auto.
- by apply aprod_S_double_summable.
Qed.
Lemma SeriesC_prod_row :
ex_seriesC h → SeriesC h = Series (λ j, Series (λ k, aprod (S j, S k))).
Proof. intros ?. by apply is_series_unique, is_seriesC_prod_row. Qed.
Lemma SeriesC_prod_column :
ex_seriesC h → SeriesC h = Series (λ k, Series (λ j, aprod (S j, S k))).
Proof. intros ?. by apply is_series_unique, is_seriesC_prod_column. Qed.
Lemma fubini_pos_seriesC_prod_lr :
ex_seriesC h → SeriesC h = SeriesC (λ a, SeriesC (λ b, h (a, b))).
Proof.
intros Hex.
rewrite SeriesC_prod_row //.
rewrite /SeriesC/aprod/countable_sum.
apply Series_ext => n.
destruct (encode_inv_nat n); simpl; [ | apply Series_0; auto].
apply Series_ext => m.
destruct (encode_inv_nat m); simpl; auto.
Qed .
Lemma fubini_pos_seriesC_prod_rl :
ex_seriesC h → SeriesC h = SeriesC (λ b, SeriesC (λ a, h (a, b))).
Proof.
intros Hex.
rewrite SeriesC_prod_column //.
rewrite /SeriesC/aprod/countable_sum.
apply Series_ext => n.
destruct (encode_inv_nat n); simpl; last first.
{ rewrite Series_0 //. intros. by case_match. }
apply Series_ext => m.
destruct (encode_inv_nat m); simpl; auto.
Qed.
Lemma fubini_pos_ex_seriesC_prod_ex_lr :
ex_seriesC h → ex_seriesC (λ a, SeriesC (λ b, h (a, b))).
Proof.
intros Hex.
apply ex_seriesC_ex_series.
rewrite /SeriesC/countable_sum.
assert (∀ n,
(from_option
(λ a, Series (λ n0, from_option (λ b, h (a, b)) 0 (encode_inv_nat n0))) 0
(encode_inv_nat n)) =
(Series (λ n0, from_option
(λ a, from_option (λ b, h (a, b)) 0 (encode_inv_nat n0)) 0
(encode_inv_nat n)))) as Haux.
{ intro n. destruct (encode_inv_nat); simpl; auto. by rewrite Series_0. }
setoid_rewrite Haux.
apply (ex_series_row_col
(λ '(n,n0),
from_option (λ a, from_option (λ b, h (a, b)) 0 (encode_inv_nat n0)) 0
(encode_inv_nat n))).
- apply aprod_double_summable in Hex as (r&Hr).
exists r.
intro n.
etrans; [ | apply (Hr (S n))].
right.
rewrite sum_n_shift'.
replace (sum_n (λ k : nat, aprod (0%nat, k)) (S n)) with 0; last first.
{ rewrite (sum_n_ext _ (λ n, 0)).
- rewrite sum_n_const; lra.
- intro; rewrite /aprod //. }
rewrite Rplus_0_r.
apply sum_n_ext; intro m.
rewrite sum_n_shift'.
replace (aprod (S m, 0%nat)) with 0; [ | by rewrite /aprod].
rewrite Rplus_0_r.
apply sum_n_ext; intro l.
rewrite /aprod.
destruct (encode_inv_nat m), (encode_inv_nat l); simpl; auto.
- intros n m.
destruct (encode_inv_nat n), (encode_inv_nat m); simpl; auto; lra.
Qed.
(* TODO: simplify using previous lemma *)
Lemma fubini_pos_ex_seriesC_prod_ex_rl :
ex_seriesC h → ex_seriesC (λ b, SeriesC (λ a, h (a, b))).
Proof.
intros Hex.
apply ex_seriesC_ex_series.
rewrite /SeriesC/countable_sum.
assert (∀ n,
(from_option
(λ b,
Series (λ n0 : nat, from_option (λ a, h (a, b)) 0 (encode_inv_nat n0))) 0
(encode_inv_nat n)) =
(Series (λ n0 : nat,
from_option
(λ b, from_option (λ a, h (a, b)) 0 (encode_inv_nat n0)) 0
(encode_inv_nat n)))) as Haux.
{
intro n. destruct (encode_inv_nat); simpl; auto.
by rewrite Series_0.
}
setoid_rewrite Haux.
apply (ex_series_row_col
(λ '(n,n0),
from_option (λ b, from_option (λ a, h (a, b)) 0 (encode_inv_nat n0)) 0
(encode_inv_nat n))).
- apply aprod_double_summable in Hex as (r&Hr).
exists r.
intro n.
etrans; [ | apply (Hr (S n))].
right.
rewrite fubini_fin_sum.
rewrite sum_n_shift'.
replace (sum_n (λ a : nat, aprod (a, 0%nat)) (S n)) with 0; last first.
{
rewrite (sum_n_ext _ (λ n, 0)).
- rewrite sum_n_const; lra.
- intro; rewrite /aprod.
case_match; auto.
}
rewrite Rplus_0_r.
apply sum_n_ext; intro m.
rewrite sum_n_shift'.
replace (aprod (0%nat, S m)) with 0; [ | by rewrite /aprod].
rewrite Rplus_0_r.
apply sum_n_ext; intro l.
rewrite /aprod.
destruct (encode_inv_nat m), (encode_inv_nat l); simpl; auto.
- intros n m.
destruct (encode_inv_nat n), (encode_inv_nat m); simpl; auto; lra.
Qed.
Lemma ex_seriesC_lmarg a :
ex_seriesC h → ex_seriesC (λ b, h (a, b)).
Proof.
intros Hex.
apply ex_seriesC_ex_series.
rewrite /SeriesC/countable_sum.
apply aprod_double_summable in Hex.
apply DS_n_to_nm in Hex as (r&Hr); last first.
{
intros n m.
rewrite /aprod.
do 4 (case_match; simpl; auto; try lra).
}
apply ex_pos_bounded_series.
- intro n; destruct (encode_inv_nat n); simpl; auto.
lra.
- exists r. intro n.
etrans; [ | apply (Hr (S n) (S (encode_nat a)))].
rewrite sum_n_shift'.
rewrite (sum_n_ext ((λ k : nat, aprod (0%nat, k))) (λ _, 0)); last first.
{
intro; rewrite /aprod //.
}
rewrite sum_n_const Rmult_0_r Rplus_0_r.
etrans; [ | apply partial_sum_elem]; last first.
{
intro.
apply partial_sum_pos.
intro.
rewrite /aprod.
do 4 (case_match; simpl; auto; try lra).
}
rewrite sum_n_shift'.
etrans; last first.
{
apply (Rplus_le_compat_l _ 0).
rewrite /aprod; lra.
}
rewrite Rplus_0_r.
right.
apply sum_n_ext.
intro m.
rewrite /aprod.
rewrite encode_inv_encode_nat.
destruct (encode_inv_nat m); simpl; auto.
Qed.
Lemma ex_seriesC_rmarg b :
ex_seriesC h → ex_seriesC (λ a, h (a, b)).
Proof.
intros Hex.
apply ex_seriesC_ex_series.
rewrite /SeriesC/countable_sum.
apply aprod_double_summable in Hex.
apply DS_n_to_nm in Hex as (r&Hr); last first.
{
intros n m.
rewrite /aprod.
do 4 (case_match; simpl; auto; try lra).
}
apply ex_pos_bounded_series.
- intro n; destruct (encode_inv_nat n); simpl; auto.
lra.
- exists r. intro n.
etrans; [ | apply (Hr (S (encode_nat b)) (S n) )].
rewrite fubini_fin_sum.
rewrite sum_n_shift'.
rewrite (sum_n_ext (λ a : nat, aprod (a, 0%nat)) (λ _, 0)); last first.
{
intro; rewrite /aprod //.
case_match; auto.
}
rewrite sum_n_const Rmult_0_r Rplus_0_r.
etrans; [ | apply partial_sum_elem]; last first.
{
intro.
apply partial_sum_pos.
intro.
rewrite /aprod.
do 4 (case_match; simpl; auto; try lra).
}
rewrite sum_n_shift'.
etrans; last first.
{
apply (Rplus_le_compat_l _ 0).
rewrite /aprod; lra.
}
rewrite Rplus_0_r.
right.
apply sum_n_ext.
intro m.
rewrite /aprod.
rewrite encode_inv_encode_nat.
destruct (encode_inv_nat m); simpl; auto.
Qed.
Lemma seriesC_lmarg_le a :
ex_seriesC h → SeriesC (λ b, h (a, b)) <= SeriesC h.
Proof.
intros Hex.
rewrite fubini_pos_seriesC_prod_rl //.
apply SeriesC_le; [ | eapply fubini_pos_ex_seriesC_prod_ex_rl; eauto].
intro b; split; [real_solver | ].
apply (SeriesC_ge_elem (λ a0, h (a0, b))); [ | apply ex_seriesC_rmarg; auto]; auto.
Qed.
Lemma seriesC_rmarg_le b :
ex_seriesC h → SeriesC (λ a, h (a, b)) <= SeriesC h.
Proof.
intros Hex.
rewrite fubini_pos_seriesC_prod_lr //.
apply SeriesC_le; [ | eapply fubini_pos_ex_seriesC_prod_ex_lr; eauto].
intro a; split; [real_solver | ].
apply (SeriesC_ge_elem (λ b0, h (a, b0))); [ | apply ex_seriesC_lmarg; auto]; auto.
Qed.
Lemma ex_seriesC_prod :
(∀ a, ex_seriesC (λ b, h (a,b))) →
ex_seriesC (λ a, SeriesC (λ b, h (a,b))) →
ex_seriesC h.
Proof.
intros Hex1 Hex2.
assert (ex_series (aprod ∘ σprod)) as Haux; last first.
{
apply ex_seriesC_ex_series.
apply (ex_series_ext _ _ aprod_σprod_countable_sum Haux).
}
apply ds_implies_exseries; auto.
apply ex_series_rows_ds.
- apply aprod_pos.
- intro m. rewrite /aprod.
destruct m as [ | m'].
{
apply ex_pos_bounded_series.
- intro; lra.
- exists 0. intro. rewrite sum_n_const; lra.
}
destruct (encode_inv_nat m') as [ |]; last first.
{
apply ex_pos_bounded_series.
- intro. case_match; lra.
- exists 0. intro. rewrite (sum_n_ext _ (λ _, 0)).
+ rewrite sum_n_const; lra.
+ intro; case_match; auto.
}
specialize (Hex1 a).
apply ex_seriesC_ex_series_inv in Hex1.
rewrite /countable_sum in Hex1.
apply ex_series_incr_1.
eapply (ex_series_ext _ _ _ Hex1). Unshelve.
intro n; simpl.
destruct (encode_inv_nat n); auto.
- apply ex_seriesC_ex_series_inv in Hex2.
rewrite /SeriesC/countable_sum in Hex2.
apply ex_series_incr_1.
eapply (ex_series_ext _ _ _ Hex2). Unshelve.
intro n; simpl.
destruct (encode_inv_nat n); simpl.
+ rewrite (Series_incr_1_aux
(λ k, match k with
| 0%nat => 0
| S n0 => _
end)); auto.
+ rewrite Series_0 //. intro; by case_match.
Qed.
End double.
Section inj.
Context `{Countable A, Countable B}.
Lemma ex_seriesC_inj (g : B->A) (f:A -> R) (Hinj:Inj (=) (=) g):
(∀ a, 0<=f a)->
ex_seriesC f -> ex_seriesC (λ b, f (g b)).
Proof.
intros ? H1.
pose (h:= (λ '(a, b), if bool_decide (g b = a) then f a else 0)).
apply (ex_seriesC_ext (λ z2, SeriesC (λ z1, h (z1, z2)))).
{ rewrite /h.
intros z2.
erewrite SeriesC_ext; first apply SeriesC_singleton_dependent.
simpl. intros; repeat case_bool_decide; by simplify_eq.
}
apply fubini_pos_seriesC_ex_double; rewrite /h.
- intros. by case_bool_decide.
- intros.
destruct (@decide (∃ b, g b = a) (make_decision _)) as [(b&<-)|n].
+ eapply ex_seriesC_ext; last apply (ex_seriesC_singleton b).
intros. simpl. repeat case_bool_decide; subst; by simplify_eq.
+ eapply ex_seriesC_ext; last apply ex_seriesC_0.
intros. rewrite bool_decide_eq_false_2; first done.
intro. apply n. naive_solver.
- eapply (ex_seriesC_le _ f); last done.
intros a.
split; first apply SeriesC_ge_0'.
+ intros. case_bool_decide; naive_solver.
+ destruct (@decide (∃ b, g b = a) (make_decision _)) as [(b&<-)|n].
* erewrite SeriesC_ext; first by erewrite (SeriesC_singleton b).
intros. repeat case_bool_decide; naive_solver.
* erewrite SeriesC_ext; first by rewrite SeriesC_0.
simpl. intros. repeat case_bool_decide; naive_solver.
Qed.
(* A lemma about rearranging SeriesC along an injective function *)
Lemma SeriesC_le_inj (f : B -> R) (h : A -> option B) :
(∀ n, 0 <= f n) →
(forall n1 n2 m, h n1 = Some m -> h n2 = Some m -> n1 = n2) ->
ex_seriesC f →
SeriesC (λ a, from_option f 0 (h a)) <= SeriesC f.
Proof.
intros Hf Hinj Hex.
rewrite {1}/SeriesC/Series.
apply Series_Ext.Lim_seq_le_loc_const.
- by apply SeriesC_ge_0'.
- rewrite /eventually. exists 0%nat.
intros n Hn.
assert (∃ l : list _, (∀ m, m∈l->(∃ k a, (k<=n)%nat /\
(@encode_inv_nat A _ _ k%nat) = Some a /\
h a = Some m)) /\
sum_n (countable_sum (λ a : A, from_option f 0 (h a))) n <=
SeriesC (λ a, if bool_decide(a ∈ l) then f a else 0)
) as H'; last first.
{ destruct H' as [?[??]].
etrans; first exact.
apply SeriesC_le'; try done.
- intros. case_bool_decide; try lra. apply Hf.
- apply ex_seriesC_list.
}
induction n.
+ destruct (@encode_inv_nat A _ _ 0%nat) eqn:Ha.
* destruct (h a) eqn : Hb.
-- exists [b]. split.
++ intros. exists 0%nat, a.
repeat split; try lia; try done.
rewrite Hb. f_equal. set_solver.
++ rewrite sum_O. rewrite /countable_sum.
rewrite Ha. simpl. rewrite Hb. simpl.
erewrite SeriesC_ext.
** erewrite SeriesC_singleton_dependent. done.
** intro. simpl.
repeat case_bool_decide; set_solver.
-- exists []. split.
++ intros; set_solver.
++ rewrite sum_O. rewrite /countable_sum.
rewrite Ha. simpl. rewrite Hb. simpl.
rewrite SeriesC_0; intros; lra.
* exists []. split.
++ intros; set_solver.
++ rewrite sum_O. rewrite /countable_sum.
rewrite Ha. simpl.
rewrite SeriesC_0; intros; lra.
+ assert (0<=n)%nat as Hge0.
* lia.
* specialize (IHn Hge0) as [l[H1 H2]].
destruct (@encode_inv_nat A _ _ (S n)%nat) eqn:Ha.
-- destruct (h a) eqn : Hb.
++ exists (b::l). split.
** intros. set_unfold.
destruct H3; subst.
--- exists (S n), a. split; try lia. split; done.
--- specialize (H1 m H3).
destruct H1 as [?[?[?[??]]]].
exists x, x0. split; try lia. by split.
** rewrite sum_Sn. rewrite {2}/countable_sum.
rewrite Ha. simpl. rewrite Hb. simpl.
rewrite (SeriesC_ext _ (λ x, (if bool_decide (x=b) then f b else 0) +
if bool_decide (x∈l) then f x else 0
)); last first.
{ intros.
case_bool_decide.
- set_unfold. destruct H3.
+ case_bool_decide; last done.
case_bool_decide.
* subst. specialize (H1 b H5).
destruct H1 as [?[?[?[??]]]].
rewrite -H6 in Hb.
assert (a = x0).
{ eapply Hinj; try done. rewrite Hb. done. }
subst. exfalso.
rewrite -H3 in Ha. assert (x≠ (S n)) by lia.
apply H7. by eapply encode_inv_nat_some_inj.
* subst. lra.
+ case_bool_decide.
{ subst. specialize (H1 b H3) as [?[?[?[??]]]].
assert (x ≠ S n) by lia.
exfalso. apply H6. eapply encode_inv_nat_some_inj; try done.
rewrite Ha H4. f_equal.
by eapply Hinj.
}
case_bool_decide; try done. lra.
- repeat case_bool_decide.
+ set_solver.
+ set_solver.
+ set_solver.
+ lra.
}
rewrite SeriesC_plus; last first.
{ by apply ex_seriesC_filter_pos. }
{ by apply ex_seriesC_singleton. }
rewrite Rplus_comm. rewrite SeriesC_singleton.
trans ((sum_n (countable_sum (λ a0 : A, from_option f 0 (h a0))) n) + f b); try lra.
done.
++ exists l. split.
** intros. specialize (H1 _ H3) as [?[?[?[??]]]].
exists x, x0. repeat split; try done. lia.
** rewrite sum_Sn. rewrite {2}/countable_sum. rewrite Ha. simpl.
rewrite Hb. simpl. etrans; last exact.
by rewrite plus_zero_r.
-- exists l. split.
++ intros. specialize (H1 _ H3) as [?[?[?[??]]]].
exists x, x0. repeat split; try done. lia.
++ rewrite sum_Sn. rewrite {2}/countable_sum. rewrite Ha. simpl.
etrans; last exact.
by rewrite plus_zero_r.
Qed.
End inj.
Lemma SeriesC_translate f loc (fpos : ∀ z, 0 <= f z) (fex : ex_seriesC f) :
(SeriesC (λ z : Z, f (z + loc)) = SeriesC f)%Z.
Proof.
opose proof (SeriesC_le_inj f (λ z, Some (z + loc))%Z _ _ _) as lb => //.
{ intros ??? h h'. inversion h ; inversion h'. lia. }
simpl in lb.
opose proof (SeriesC_le_inj (λ z, f (z + loc))%Z (λ z, Some (z - loc))%Z _ _ _) as ub => //.
{ intros ??? h h'. inversion h ; inversion h'. lia. }
1: apply ex_seriesC_inj => //.
{ intros ?? h. inversion h. lia. }
simpl in ub.
setoid_rewrite Z.sub_simpl_r in ub. apply Rle_antisym => //.
Qed.
Section Inj_finite.
Lemma SeriesC_filter_finite_1 `{Countable A} (M:nat) (f:A -> R) (g: fin M -> R) h:
Inj eq eq h -> (0 < M)%nat -> (∀ a: A, 0 <= f a <= 1) -> (∀ b: fin M, 0 <= g b <= 1) ->
(∀ (a : A) (b : fin M), a = h b → f a <= g b) ->
SeriesC (λ a : A, if bool_decide (∃ y : fin M, a = h y) then f a else 0) <= SeriesC g.
Proof.
intros Hinj Hineq Hf Hg Hfg.
rewrite {1}/SeriesC. apply series_bounded.
{ intros. apply countable_sum_ge_0. intros; case_bool_decide; naive_solver. }
2:{ eapply ex_seriesC_ex_series_inv, ex_seriesC_ext; last eapply ex_seriesC_list.
instantiate (2:= h <$> enum (fin M)).
intros. case_bool_decide as H1; case_bool_decide as H2; try done.
- exfalso.
apply H2. destruct H1. subst. apply list_elem_of_fmap_2, elem_of_enum.
- exfalso. apply H1. rewrite list_elem_of_fmap in H2. destruct H2 as [y[??]].
naive_solver.
}
intros n.
cut (∃ l', NoDup l' /\ (∀ y, y ∈ l' <-> (∃ x, x = h y /\ (encode_nat x <= n)%nat)) /\
sum_n (countable_sum (λ a : A, if bool_decide (∃ y : fin M, a = h y) then f a else 0)) n <= SeriesC (λ x, if bool_decide (x ∈ l') then g x else 0)
).
{ intros [?[?[??]]]. etrans; first exact. apply SeriesC_filter_leq; last apply ex_seriesC_finite.
intros; naive_solver.
}
induction n.
- rewrite sum_O /countable_sum. destruct (encode_inv_nat _) eqn:H1; simpl.
+ case_bool_decide as H2.
* destruct H2 as [y?].
exists [y].
repeat split.
-- repeat constructor. set_solver.
-- intros. exists a. split; first set_solver.
apply encode_inv_Some_nat in H1. lia.
-- intros [?[??]].
subst. assert (encode_nat (h y0) = 0%nat) by lia.
apply encode_inv_Some_nat in H1. rewrite -H1 in H0.
apply encode_nat_inj in H0. apply Hinj in H0. set_solver.
-- subst. erewrite SeriesC_ext.
{ erewrite SeriesC_singleton_dependent. by apply Hfg. }
intros. repeat case_bool_decide; set_solver.
* exists []. repeat split.
-- constructor.
-- set_solver.
-- intros [? [??]]. exfalso. apply H2. apply encode_inv_Some_nat in H1.
assert (encode_nat x = 0%nat) by lia. rewrite -H1 in H4. apply encode_nat_inj in H4; subst.
naive_solver.
-- apply SeriesC_ge_0'. intros. case_bool_decide; naive_solver.
+ exists []. repeat split.
-- constructor.
-- set_solver.
-- intros [?[??]]. assert (encode_nat x = 0%nat) by lia. rewrite -H3 in H1.
by rewrite encode_inv_encode_nat in H1.
-- apply SeriesC_ge_0'. intros. case_bool_decide; naive_solver.
- destruct IHn as [l'[Hnd[H1 H2]]].
rewrite sum_Sn /countable_sum. destruct (encode_inv_nat _) eqn:H3; simpl.
+ case_bool_decide as H4.
* destruct H4 as [y?].
exists (y::l'). repeat split.
-- constructor; last done. move /H1. intros [?[??]]. subst.
apply encode_inv_Some_nat in H3. lia.
-- move /elem_of_cons. intros [->|?].
++ exists a. split; first done. apply encode_inv_Some_nat in H3. lia.
++ subst. rewrite H1 in H4. naive_solver.
-- intros [?[??]]. subst.
rewrite Nat.le_succ_r in H5. destruct H5.
++ apply list_elem_of_further. rewrite H1.
eexists _; by split.
++ apply encode_inv_Some_nat in H3. rewrite -H3 in H0. apply encode_nat_inj in H0.
apply Hinj in H0. set_solver.
-- rewrite (SeriesC_ext _ (λ x : fin M, (if bool_decide (x ∈ l') then g x else 0)+if bool_decide (x = y) then g x else 0)).
++ rewrite SeriesC_plus; try apply ex_seriesC_finite.
apply Rplus_le_compat; first done.
rewrite SeriesC_singleton_dependent.
by apply Hfg.
++ intros n'. repeat case_bool_decide; try done; try lra; subst.
** rewrite H1 in H5. destruct H5 as [?[??]]. subst.
apply encode_inv_Some_nat in H3. lia.
** set_solver.
** set_solver.
** set_solver.
** set_solver.
* exists l'. repeat split; try done.
-- intros. naive_solver.
-- intros [?[??]]. rewrite H1. subst. eexists _; split; first done.
rewrite Nat.le_succ_r in H5. destruct H5; try lia.
exfalso. apply H4. apply encode_inv_Some_nat in H3. rewrite -H3 in H0.
apply encode_nat_inj in H0. naive_solver.
-- rewrite plus_zero_r. done.
+ exists l'. repeat split; try done.
* intros. naive_solver.
* elim. intros ?[??]. subst. rewrite H1. eexists _; split; first done.
rewrite Nat.le_succ_r in H4. destruct H4; first done.
rewrite -H0 in H3. by rewrite encode_inv_encode_nat in H3.
* by rewrite plus_zero_r.
Qed.
Lemma SeriesC_filter_finite_1_bounds `{Countable A} (M:nat) (f:A -> R) (g: fin M -> R) h r:
Inj eq eq h -> (0 < M)%nat -> (0<r)-> (∀ a: A, 0 <= f a <= r) -> (∀ b: fin M, 0 <= g b <= r) ->
(∀ (a : A) (b : fin M), a = h b → f a <= g b) ->
SeriesC (λ a : A, if bool_decide (∃ y : fin M, a = h y) then f a else 0) <= SeriesC g.
Proof.
intros Hinj Hm Hr Hf Hg Hfg.
apply (Rmult_le_reg_r (/r)).
{ rewrite -Rdiv_1_l. apply Rdiv_lt_0_compat; lra. }
rewrite -!SeriesC_scal_r.
erewrite (SeriesC_ext _ (λ x : A, (if bool_decide (∃ y : fin M, x = h y) then (λ x, f x / r) x else 0))); last first.
{ intros. case_bool_decide; lra. }
apply SeriesC_filter_finite_1; try done.
- intros; split.
+ apply Rcomplements.Rdiv_le_0_compat; try lra. naive_solver.
+ rewrite Rcomplements.Rle_div_l; last naive_solver. rewrite Rmult_1_l. naive_solver.
- intros; split.
+ apply Rcomplements.Rdiv_le_0_compat; try lra. naive_solver.
+ rewrite Rcomplements.Rle_div_l; last naive_solver. rewrite Rmult_1_l. naive_solver.
- intros. rewrite Rdiv_def. apply Rmult_le_compat_r; last naive_solver.
rewrite -Rdiv_1_l. apply Rcomplements.Rdiv_le_0_compat; try lra.
Qed.
Lemma SeriesC_filter_finite_1' (N M:nat) (f:fin N -> R) (g: fin M -> R) h:
Inj eq eq h -> (0 < M <= N)%nat -> (∀ a: fin N, 0 <= f a <= 1) -> (∀ b: fin M, 0 <= g b <= 1) ->
(∀ (a : fin N) (b : fin M), a = h b → f a <= g b) ->
SeriesC (λ a : fin N, if bool_decide (∃ y : fin M, a = h y) then f a else 0) <= SeriesC g.
Proof.
intros Hinj Hineq Hf Hg Hfg.
apply SeriesC_filter_finite_1; try done.
lia.
Qed.
Lemma SeriesC_filter_finite_2 (N M:nat) (f:fin N -> R) h:
Inj eq eq h -> (0 < M <= N)%nat -> (∀ a: fin N, 0 <= f a <= 1) ->
SeriesC (λ a : fin N, if bool_decide (∃ y : fin M, a = h y) then 0 else f a) <= (N-M)%nat.
Proof.
intros Hinj Hineq Hf. rewrite minus_INR; last naive_solver.
rewrite Rcomplements.Rle_minus_r.
replace (INR M) with (SeriesC (λ a : fin N, if bool_decide (∃ y : fin M, a = h y) then 1 else 0)).
- rewrite -SeriesC_plus; try apply ex_seriesC_finite.
trans (SeriesC (λ _:fin N, 1)).
+ apply SeriesC_le; last apply ex_seriesC_finite.
intros n; case_bool_decide; try lra.
rewrite Rplus_0_r; naive_solver.
+ rewrite SeriesC_finite_mass fin_card. lra.
- replace (INR M) with (SeriesC (λ _:fin M, 1)); last (rewrite SeriesC_finite_mass fin_card; lra).
apply Rle_antisym.
+ apply SeriesC_filter_finite_1'; try done; intros; lra.
+ etrans; last first.
* eapply SeriesC_le_inj; last apply ex_seriesC_finite.
-- intros. case_bool_decide; lra.
-- intros ???. instantiate (2 := (λ x, (Some (h x)))). simpl.
intros H1 H2. rewrite -H1 in H2. inversion H2. by apply Hinj.
* apply SeriesC_le; last apply ex_seriesC_finite.
intros n. split; first lra.
simpl. case_bool_decide; first done.
exfalso; naive_solver.
Qed.
Lemma SeriesC_fin_in_set (N : nat) (ns : gset nat):
(forall x, x ∈ ns -> (x < S N)%nat ) ->
(SeriesC (λ x : fin (S N), if bool_decide (fin_to_nat x ∈ ns) then 1 else 0) = size ns).
Proof.
revert ns.
epose proof (set_ind
(λ (s : gset nat), (forall x, x ∈ s -> ( x < S N)%nat ) ->
(SeriesC (λ x : fin (S N), if bool_decide (fin_to_nat x ∈ s) then 1 else 0) = size s))).
apply H.
- solve_proper.
- intro Hlt.
rewrite size_empty.
apply SeriesC_0.
intro.
rewrite bool_decide_eq_false_2; auto.
set_solver.
- intros x ns HnElem Hseries Hlt.
rewrite size_union; [ | set_solver].
erewrite SeriesC_ext; last first.
+ intros.
erewrite bool_decide_ext; [ | apply elem_of_union ].
done.
Unshelve. solve_decision.
+ etrans.
* symmetry.
eapply is_seriesC_filter_union.
2: { apply SeriesC_correct, ex_seriesC_finite. }
intro; simpl; lra.
* rewrite size_singleton plus_INR /=.
assert (x < S N)%nat as Hxlt.
{
apply Hlt. set_solver.
}
rewrite {1}(SeriesC_ext _ (λ n, if bool_decide (n = (nat_to_fin Hxlt)) then 1 else 0));
last first.
{
intro n.
erewrite bool_decide_ext; [ | apply elem_of_singleton ].
case_bool_decide as Hnx ; simplify_eq.
- rewrite bool_decide_eq_true_2; auto.
by rewrite nat_to_fin_to_nat.
- rewrite bool_decide_eq_false_2; auto.
intros ->.
apply Hnx.
by rewrite fin_to_nat_to_fin.
}
rewrite SeriesC_singleton Hseries; [ | intros; apply Hlt; set_solver ].
rewrite SeriesC_0; [lra |].
intros.
rewrite bool_decide_eq_false_2; auto.
set_solver.
Unshelve. solve_decision.
Qed.
Lemma SeriesC_fin_in_set' (N : nat) (ns : gset nat) v:
(forall x, x ∈ ns -> (x < S N)%nat ) ->
(SeriesC (λ x : fin (S N), if bool_decide (fin_to_nat x ∈ ns) then v else 0) = v* size ns).
Proof.
erewrite (SeriesC_ext _ (λ x : fin (S N), v* if bool_decide (fin_to_nat x ∈ ns) then 1 else 0)).
- intros. rewrite SeriesC_scal_l.
by rewrite SeriesC_fin_in_set.
- intros.
case_bool_decide; lra.
Qed.
Lemma SeriesC_fin_not_in_set (N : nat) (ns : gset nat) :
(forall x, x ∈ ns -> (x < S N)%nat ) ->
(SeriesC (λ x : fin (S N), if bool_decide (fin_to_nat x ∉ ns) then 1 else 0) = (N + 1 - size ns))%R.
Proof.
intros Hlt.
apply Req_minus_r.
rewrite -(SeriesC_fin_in_set N); auto.
rewrite -SeriesC_plus; [ | apply ex_seriesC_finite | apply ex_seriesC_finite ].
erewrite (SeriesC_ext _ (λ _, 1)); last first.
{
intros.
case_bool_decide; case_bool_decide.
- set_solver.
- lra.
- lra.
- set_solver.
}
rewrite SeriesC_finite_mass fin_card S_INR.
lra.
Qed.
Lemma SeriesC_fin_not_in_set' (N : nat) (ns : gset nat) v:
(forall x, x ∈ ns -> (x < S N)%nat ) ->
(SeriesC (λ x : fin (S N), if bool_decide (fin_to_nat x ∉ ns) then v else 0) = v*(N + 1 - size ns))%R.
Proof.
erewrite (SeriesC_ext _ (λ x : fin (S N), v* if bool_decide (fin_to_nat x ∉ ns) then 1 else 0)).
- intros. rewrite SeriesC_scal_l.
by rewrite SeriesC_fin_not_in_set.
- intros.
case_bool_decide; lra.
Qed.
End Inj_finite.
Section gmap.
(* very specialized lemmas for elton *)
Lemma ex_seriesC_gmap_insert `{Countable X} `{Countable Y} l g f:
(∀ x, 0<= f x) -> (∀ x, 0 <= g x) ->
ex_seriesC f ->
ex_seriesC g ->
ex_seriesC (λ (m : gmap X Y), match m!!l with
| Some z => f (delete l m) * g z
| None => 0
end
).
Proof.
intros H1 H2 H3 H4.
pose (f' := (λ '(m, z),
match z with
| Some z => f m * g z
| None => 0
end
)).
pose (g' := (λ (m:gmap X Y), (delete l m, m!!l))).
apply (ex_seriesC_ext (λ m, f' (g' m))); first done.
apply ex_seriesC_inj.
{ intros ??.
rewrite /g'.
intros. simplify_eq.
apply map_eq.
intros i.
destruct (decide (i=l)); subst; simplify_map_eq; first done.
erewrite <-lookup_delete_ne; last done.
erewrite <-(lookup_delete_ne y); last done.
by f_equal.
}
{ intros.
rewrite /f'.
case_match.
subst.
case_match; real_solver.
}
rewrite /f'.
apply ex_seriesC_prod.
- intros. case_match; real_solver.
- intros a.
apply (ex_seriesC_le _ (λ b, f a * from_option g 0 b)).
{ intros. case_match; real_solver. }
apply ex_seriesC_scal_l.
apply ex_seriesC_from_option; naive_solver.
- apply (ex_seriesC_le _ (λ a, SeriesC (λ b, f a * from_option g 0 b))).
{ intros. split.
- apply SeriesC_ge_0'. real_solver.
- right.
apply SeriesC_ext.
intros. case_match; real_solver.
}
setoid_rewrite SeriesC_scal_l.
by apply ex_seriesC_scal_r.
Qed.
Lemma SeriesC_gmap_insert_le_1 `{Countable X} `{Countable Y} f g l:
(∀ x, 0<= f x) -> (∀ x, 0 <= g x) ->
ex_seriesC f ->
ex_seriesC g ->
SeriesC f<=1 ->
SeriesC (g) <=1 ->
SeriesC (λ (m : gmap X Y), match m!!l with
| Some z => f (delete l m) * g z
| None => 0
end
) <= 1.
Proof.
intros H1 H2 H3 H4 H5 H6.
pose (f' := (λ '(m, z),f m * g z
)).
pose (g' := (λ (m:gmap X Y), match m!!l with
| Some z => Some (delete l m, z)
| None => None
end
)).
erewrite (SeriesC_ext _ (λ m, from_option f' 0 (g' m))); last first.
{ intros. rewrite /g'/f'. by case_match. }
etrans; first apply SeriesC_le_inj.
- intros. rewrite /f'.
case_match.
real_solver.
- rewrite /g'.
intros. repeat case_match; simplify_eq.
apply map_eq.
intros i.
destruct (decide (i=l)); subst; simplify_map_eq; first done.
erewrite <-lookup_delete_ne; last done.
erewrite <-(lookup_delete_ne n2); last done.
by f_equal.
- rewrite /f'.
apply ex_seriesC_prod.
+ real_solver.
+ intros.
by apply ex_seriesC_scal_l.
+ setoid_rewrite SeriesC_scal_l.
by apply ex_seriesC_scal_r.
- rewrite /f'.
rewrite fubini_pos_seriesC_prod_lr; last first.
+ apply ex_seriesC_prod.
* real_solver.
* intros. by apply ex_seriesC_scal_l.
* setoid_rewrite SeriesC_scal_l.
by apply ex_seriesC_scal_r.
+ real_solver.
+ setoid_rewrite (SeriesC_scal_l _ (f _)).
setoid_rewrite (SeriesC_scal_r).
replace (1) with (1*1) by lra.
apply Rmult_le_compat; try done; by apply SeriesC_ge_0'.
Qed.
End gmap.
Ltac series_solver_partial :=
match goal with
| |- 0 <= SeriesC _ => apply SeriesC_ge_0'
| |- SeriesC _ = SeriesC _ => apply SeriesC_ext
end.
Ltac series := repeat (series_solver_partial || real_solver_partial).
Context `{Countable A}.
Implicit Types f g : A → R.
Lemma limC_is_sup (h: A → R) r :
(∀ n, 0 <= h n) →
is_seriesC h r →
is_sup_seq (sumC_n h) (Rbar.Finite r).
Proof.
intros Hge Hs.
rewrite /is_seriesC in Hs.
eapply (lim_is_sup (countable_sum h) r); auto.
intro n. rewrite /countable_sum /from_option; edestruct (@encode_inv_nat A _ H n); auto ; lra.
Qed.
Lemma sup_is_limC (h: A → R) r :
(∀ n, 0 <= h n) →
is_sup_seq (sumC_n h) (Rbar.Finite r) →
is_seriesC h r.
Proof.
intros Hge Hsup.
rewrite /is_seriesC.
eapply (sup_is_lim); auto.
intro n; rewrite /countable_sum /from_option; destruct (encode_inv_nat _); auto; lra.
Qed.
End positive.
Section bounds.
Context `{Countable A}.
Definition is_lubC (h: A → R) (u : Rbar) :=
(∀ a, Rbar_le (h a) u) /\ (∀ u', (∀ a, Rbar_le (h a) u') → Rbar_le u u').
Lemma ex_lubC (h : A → R) :
{u | is_lubC h u}.
Proof.
destruct (Lub_Rbar_correct ((λ r : R, ∃ a0 : A, h a0 = r))) as [H1 H2].
exists (Lub_Rbar (λ (r : R), exists a, h a = r)); split.
- intro a.
apply H1; eauto.
- intros u' Hu'.
apply H2; auto.
rewrite /is_ub_Rbar.
intros x (a & <-); auto.
Qed.
Definition LubC (h : A → R) := proj1_sig (ex_lubC h).
Lemma LubC_correct (h : A → R) :
is_lubC h (LubC h).
Proof.
rewrite /LubC ; by case: ex_lubC => l /= Hl.
Qed.
Lemma seriesC_le_lub (h : A → R) :
ex_seriesC h →
is_finite (LubC h) →
ex_seriesC (λ a : A, real (LubC h)) →
SeriesC h <= SeriesC (λ a : A, real (LubC h)).
Proof.
intros Hex Hfin Hex2.
apply SeriesC_le'; auto.
intro n.
destruct (LubC_correct h) as [H1 H2].
apply rbar_le_finite; auto.
Qed.
Definition is_glbC (h: A → R) (l : Rbar) :=
(∀ a, Rbar_le l (h a) ) ∧ (∀ l', (∀ a, Rbar_le l' (h a)) → Rbar_le l' l).
Lemma ex_glbC (h : A → R) :
{u | is_glbC h u}.
Proof.
destruct (Glb_Rbar_correct ((λ r : R, ∃ a0 : A, h a0 = r))) as [H1 H2].
exists (Glb_Rbar (λ (r : R), exists a, h a = r)); split.
- intro a.
apply H1; eauto.
- intros u' Hu'.
apply H2; auto.
rewrite /is_lb_Rbar.
intros x (a & <-); auto.
Qed.
Definition GlbC (h : A → R) := proj1_sig (ex_glbC h).
Lemma GlbC_correct (h : A → R) :
is_glbC h (GlbC h).
Proof.
rewrite /GlbC ; by case: ex_glbC => l /= Hl.
Qed.
Lemma seriesC_le_glb (h : A → R) :
ex_seriesC h →
is_finite (GlbC h) →
ex_seriesC (λ a : A, real (GlbC h)) →
SeriesC (λ a : A, real (GlbC h)) <= SeriesC h.
Proof.
intros Hex Hfin Hex2.
apply SeriesC_le'; auto.
intro n.
destruct (GlbC_correct h) as [H1 H2].
apply finite_rbar_le; auto.
Qed.
End bounds.
Section fubini.
Context `{Countable A, Countable B}.
(*
The following three lemmas have been proven for
Series, so the only missing part is lifting them
to SeriesC
*)
Lemma fubini_pos_seriesC_ex (h : A * B → R) :
(∀ a b, 0 <= h (a, b)) →
(∀ a, ex_seriesC (λ b, h (a, b))) →
(ex_seriesC (λ a, SeriesC (λ b, h (a, b)))) →
(∀ b, ex_seriesC (λ a, h (a, b))).
Proof.
intros Hpos Hex1 Hex2 b.
set (f := λ '(n, m), countable_sum (λ a, countable_sum (λ b, h (a,b)) m) n).
assert (∀ m, ex_series (λ n, f (n, m))) as H1.
{
apply fubini_pos_series_ex.
- intros n m.
rewrite /f/countable_sum.
destruct (encode_inv_nat n);
destruct (encode_inv_nat m);
simpl; real_solver.
- intro n. rewrite /f {1}/countable_sum.
destruct (encode_inv_nat n); simpl.
+ apply Hex1.
+ exists 0. apply is_series_0; auto.
- rewrite /f/countable_sum/=.
apply ex_seriesC_ex_series_inv in Hex2.
rewrite /SeriesC/countable_sum/= in Hex2.
eapply ex_series_ext; [ | apply Hex2].
intro n; simpl.
destruct (encode_inv_nat n); simpl; auto.
symmetry; apply Series_0; auto.
}
apply ex_seriesC_ex_series.
eapply ex_series_ext; [ | apply (H1 (encode_nat b)) ].
intros; simpl.
apply countable_sum_ext => a.
rewrite /countable_sum encode_inv_encode_nat //.
Qed.
Lemma fubini_pos_seriesC_ex_double (h : A * B → R) :
(∀ a b, 0 <= h (a, b)) →
(∀ a, ex_seriesC (λ b, h (a, b))) →
(ex_seriesC (λ a, SeriesC (λ b, h (a, b)))) →
(ex_seriesC (λ b, SeriesC (λ a, h (a, b)))).
Proof.
intros Hpos Hex1 Hex2.
set (f := λ '(n, m), countable_sum (λ a, countable_sum (λ b, h (a,b)) m) n).
assert (ex_series (λ m, Series (λ n, f (n, m)))) as H1.
{
apply fubini_pos_series_ex_double.
- intros n m.
rewrite /f/countable_sum.
destruct (encode_inv_nat n);
destruct (encode_inv_nat m);
simpl; real_solver.
- intro n. rewrite /f {1}/countable_sum.
destruct (encode_inv_nat n); simpl.
+ apply Hex1.
+ exists 0. apply is_series_0; auto.
- rewrite /f/countable_sum/=.
apply ex_seriesC_ex_series_inv in Hex2.
rewrite /SeriesC/countable_sum/= in Hex2.
eapply ex_series_ext; [ | apply Hex2].
intro n; simpl.
destruct (encode_inv_nat n); simpl; auto.
symmetry; apply Series_0; auto.
}
apply ex_seriesC_ex_series.
eapply ex_series_ext; [ | apply H1 ].
intros; simpl.
rewrite /SeriesC /countable_sum.
destruct (encode_inv_nat n); simpl; auto.
apply Series_0.
intro m.
destruct (encode_inv_nat m); simpl; auto.
Qed.
Lemma fubini_pos_seriesC (h : A * B → R) :
(∀ a b, 0 <= h (a, b)) →
(∀ a, ex_seriesC (λ b, h (a, b))) →
(ex_seriesC (λ a, SeriesC (λ b, h (a, b)))) →
SeriesC (λ b, SeriesC (λ a, h (a, b))) =
SeriesC (λ a, SeriesC (λ b, h (a, b))).
Proof.
intros Hpos Hex1 Hex2.
set (f := λ '(n, m), countable_sum (λ a, countable_sum (λ b, h (a,b)) m) n).
assert (Series (λ m, Series (λ n, f (n, m))) = Series (λ n, Series (λ m, f (n, m)))) as H1.
{
apply fubini_pos_series.
- intros n m.
rewrite /f/countable_sum.
destruct (encode_inv_nat n);
destruct (encode_inv_nat m);
simpl; real_solver.
- intro n. rewrite /f {1}/countable_sum.
destruct (encode_inv_nat n); simpl.
+ apply Hex1.
+ exists 0. apply is_series_0; auto.
- rewrite /f/countable_sum/=.
apply ex_seriesC_ex_series_inv in Hex2.
rewrite /SeriesC/countable_sum/= in Hex2.
eapply ex_series_ext; [ | apply Hex2].
intro n; simpl.
destruct (encode_inv_nat n); simpl; auto.
symmetry; apply Series_0; auto.
}
etrans; [ etrans; [ | exact H1] | ].
- rewrite /f/SeriesC/countable_sum.
apply Series_ext.
intro n.
destruct (encode_inv_nat n); simpl; auto.
symmetry; apply Series_0; auto.
intro m.
destruct (encode_inv_nat m); simpl; auto.
- rewrite /f/SeriesC/countable_sum.
apply Series_ext.
intro n.
destruct (encode_inv_nat n); simpl; auto.
apply Series_0; auto.
Qed.
Lemma fubini_pos_seriesC' (h : A -> B → R) :
(∀ a b, 0 <= h a b) →
(∀ a, ex_seriesC (λ b, h a b)) →
(ex_seriesC (λ a, SeriesC (λ b, h a b))) →
SeriesC (λ b, SeriesC (λ a, h a b)) =
SeriesC (λ a, SeriesC (λ b, h a b)).
Proof.
intros.
pose (h' := λ '(a,b), h a b).
assert (forall a b, h a b = h' (a,b)) as H'.
{ intros. by rewrite /h'. }
setoid_rewrite H'.
apply fubini_pos_seriesC.
all: by setoid_rewrite <-H'.
Qed.
End fubini.
Section mct.
Context `{Countable A}.
Lemma MCT_seriesC (h : nat → A → R) (l : nat → R) (r : R) :
(∀ n a, 0 <= (h n a)) →
(∀ n a, (h n a) <= (h (S n) a)) →
(∀ a, exists s, ∀ n, h n a <= s ) →
(∀ n, is_seriesC (h n) (l n)) →
is_sup_seq l (Rbar.Finite r) →
SeriesC (λ a, Sup_seq (λ n, h n a)) = r.
Proof.
intros Hpos Hle1 Hle2 Hsr Hsup.
set (f := λ n m, countable_sum (λ a, h n a) m).
assert (Series (λ m, Sup_seq (λ n, f n m)) = r ) as H1.
{
apply (MCT_series f l r).
- intros n m.
rewrite /f/countable_sum.
destruct (encode_inv_nat m);
simpl; real_solver.
- intros n m.
rewrite /f/countable_sum.
destruct (encode_inv_nat m);
simpl; real_solver.
- intro n.
rewrite /f/countable_sum.
destruct (encode_inv_nat) as [a | ].
+ destruct (Hle2 a) as [s Hs].
exists s; auto.
+ exists 0; real_solver.
- intro n.
specialize (Hsr n).
eapply is_series_ext; [ | exact Hsr].
intro m.
rewrite /f /countable_sum.
destruct (encode_inv_nat m); simpl; auto.
- auto.
}
rewrite -H1.
apply Series_ext.
intro n.
rewrite /f/countable_sum.
destruct (encode_inv_nat n); simpl; auto.
symmetry.
apply sup_seq_const.
Qed.
Lemma MCT_ex_seriesC (h : nat → A → R) (l : nat → R) (r : R) :
(∀ n a, 0 <= (h n a)) →
(∀ n a, (h n a) <= (h (S n) a)) →
(∀ a, exists s, ∀ n, h n a <= s ) →
(∀ n, is_seriesC (h n) (l n)) →
is_sup_seq l (Rbar.Finite r) →
ex_seriesC (λ a, Sup_seq (λ n, h n a)).
Proof.
intros Hpos Hle1 Hle2 Hsr Hsup.
set (f := λ n m, countable_sum (λ a, h n a) m).
assert (ex_series (λ m, real (Sup_seq (λ n, f n m)))) as H1.
{
apply (MCT_ex_series f l r).
- intros n m.
rewrite /f/countable_sum.
destruct (encode_inv_nat m);
simpl; real_solver.
- intros n m.
rewrite /f/countable_sum.
destruct (encode_inv_nat m);
simpl; real_solver.
- intro n.
rewrite /f/countable_sum.
destruct (encode_inv_nat) as [a | ].
+ destruct (Hle2 a) as [s Hs].
exists s; auto.
+ exists 0; real_solver.
- intro n.
specialize (Hsr n).
eapply is_series_ext; [ | exact Hsr].
intro m.
rewrite /f /countable_sum.
destruct (encode_inv_nat m); simpl; auto.
- auto.
}
eapply ex_series_ext; [ | apply H1].
intro n.
rewrite /f/countable_sum.
destruct (encode_inv_nat n); simpl; auto.
apply sup_seq_const.
Qed.
Lemma SeriesC_Sup_seq_swap (r : R) (l : nat → R) (h : nat → A → R) :
(∀ n a, 0 <= (h n a)) →
(∀ n a, (h n a) <= (h (S n) a)) →
(∀ a, exists s, ∀ n, h n a <= s ) →
(∀ n, is_seriesC (h n) (l n)) →
(∀ n, l n <= r) →
SeriesC (λ a, Sup_seq (λ n, h n a)) = Sup_seq (λ n, SeriesC (h n)).
Proof.
intros ?????.
eapply MCT_seriesC; [done..|].
assert (∀ n, SeriesC (λ a : A, h n a) = l n) as Heq.
{ intros ?. by eapply is_seriesC_unique. }
erewrite Sup_seq_ext; last first.
{ intros n. rewrite Heq //. }
rewrite (Rbar_le_sandwich 0 r).
- apply Sup_seq_correct.
- apply (Sup_seq_minor_le _ _ 0%nat)=>/=.
rewrite -Heq. by apply SeriesC_ge_0'.
- by apply upper_bound_ge_sup=>/=.
Qed.
End mct.
Section double.
Context `{Countable A, Countable B}.
Variable (h : A * B → R).
Variable (POS : ∀ a b, 0 <= h (a, b)).
Definition σprod (n : nat) :=
match @encode_inv_nat (A*B) _ _ n with
| Some (a, b) => (S (encode_nat a), S (encode_nat b))
| None => (O, O)
end.
Definition aprod (mn : nat * nat) :=
match mn with
| (S m, S n) =>
match @encode_inv_nat A _ _ m, @encode_inv_nat B _ _ n with
| Some a, Some b => h (a, b)
| _, _ => 0
end
| _ => 0
end.
Lemma aprod_pos: ∀ m n, 0 <= aprod (m, n).
Proof .
intros m n. rewrite /aprod.
do 4 (case_match; try lra). auto.
Qed.
Lemma σprod_inj n n' :
aprod (σprod n) ≠ 0 → σprod n = σprod n' → n = n'.
Proof.
rewrite /σprod /aprod.
destruct (encode_inv_nat n) as [[a b]|] eqn: Heq1 => /=; [|nra].
destruct (encode_inv_nat (encode_nat a)) as [a'|] eqn: Heq2; [|nra].
destruct (encode_inv_nat (encode_nat b)) as [b'|] eqn: Heq3; [|nra].
intros _.
destruct (encode_inv_nat n') as [[a'' b'']|] eqn:Heq4;
intros [= <-%(inj _) <-%(inj _)].
rewrite encode_inv_encode_nat in Heq2.
rewrite encode_inv_encode_nat in Heq3.
simplify_eq. rewrite -Heq1 in Heq4.
by eapply encode_inv_nat_some_inj.
Qed.
Lemma σprod_cov n : aprod n ≠ 0 → ∃ m, σprod m = n.
Proof.
destruct n as [[] []]=> //=.
case_match eqn:Ha; [|lra].
case_match eqn:Hb; [|lra].
intros _.
exists (encode_nat (a, b)).
rewrite /σprod.
rewrite encode_inv_encode_nat.
erewrite encode_inv_Some_nat; [|done].
erewrite encode_inv_Some_nat; [|done].
done.
Qed.
Lemma aprod_σprod_countable_sum n :
(aprod ∘ σprod) n = countable_sum h n.
Proof.
rewrite /aprod/σprod/countable_sum/=.
destruct (encode_inv_nat n) as [[]|] eqn:Heq; simpl; [|lra].
do 2 rewrite encode_inv_encode_nat.
lra.
Qed.
Lemma ex_series_σprod :
ex_seriesC h → ex_series (aprod ∘ σprod).
Proof.
intros Hex.
apply ex_pos_bounded_series.
+ intros n. simpl. destruct (σprod n). apply aprod_pos.
+ exists (SeriesC h).
apply ex_seriesC_ex_series_inv in Hex.
intro n.
etrans; last first.
* eapply series_pos_partial_le; [|done].
intro m. apply countable_sum_ge_0. by intros [].
* apply sum_n_le => m.
rewrite aprod_σprod_countable_sum //.
Qed.
#[local] Hint Resolve aprod_pos σprod_inj σprod_cov ex_series_σprod : core.
Lemma aprod_double_summable:
ex_seriesC h → double_summable aprod.
Proof. intros Hex. eapply (summable_implies_ds aprod σprod); auto. Qed.
Lemma aprod_S_double_summable :
ex_seriesC h → double_summable (λ '(j, k), aprod (S j, S k)).
Proof.
intros [r Hr]%aprod_double_summable.
rewrite /double_summable.
exists r.
intros n.
erewrite sum_n_ext; last first.
{ intros m. rewrite (sum_n_shift (λ k, aprod (S m, k))) //. }
rewrite sum_n_plus /plus /=.
rewrite (sum_n_shift (λ k, sum_n (λ j, aprod (k, j)) (S n))).
rewrite sum_n_const.
assert (0 <= sum_n (λ j, aprod (0%nat, j)) (S n)) by eapply partial_sum_pos=>//.
specialize (Hr (S n)).
lra.
Qed.
Lemma is_seriesC_prod_row:
ex_seriesC h → is_seriesC h (Series (λ j, Series (λ k, aprod (S j, S k)))).
Proof.
intro Hex.
apply (is_series_ext (aprod ∘ σprod)); [apply aprod_σprod_countable_sum|].
eapply is_series_chain; [apply is_series_double_covering'; auto|].
cut (Series (λ j, Series (λ k, aprod (j, k))) =
(Series (λ j, Series (λ k, aprod (S j, S k))))).
{ intros <-. apply Series_correct. eexists.
eapply (is_series_double_covering aprod σprod); auto. }
rewrite Series_incr_1; last first.
{ eexists. eapply is_series_double_covering; eauto. }
rewrite {1}/aprod Series_0 // Rplus_0_l.
apply Series_ext => n.
rewrite Series_incr_1; last first.
{ apply ex_series_row; [|auto]. by apply aprod_double_summable. }
rewrite {1}/aprod Rplus_0_l => //=.
Qed.
Lemma is_seriesC_prod_column:
ex_seriesC h → is_seriesC h (Series (λ k, Series (λ j, aprod (S j, S k)))).
Proof.
intros Hex.
rewrite -(double_summable_fubini (λ '(j, k), aprod (S j, S k))).
- by apply is_seriesC_prod_row.
- intros []; auto.
- by apply aprod_S_double_summable.
Qed.
Lemma SeriesC_prod_row :
ex_seriesC h → SeriesC h = Series (λ j, Series (λ k, aprod (S j, S k))).
Proof. intros ?. by apply is_series_unique, is_seriesC_prod_row. Qed.
Lemma SeriesC_prod_column :
ex_seriesC h → SeriesC h = Series (λ k, Series (λ j, aprod (S j, S k))).
Proof. intros ?. by apply is_series_unique, is_seriesC_prod_column. Qed.
Lemma fubini_pos_seriesC_prod_lr :
ex_seriesC h → SeriesC h = SeriesC (λ a, SeriesC (λ b, h (a, b))).
Proof.
intros Hex.
rewrite SeriesC_prod_row //.
rewrite /SeriesC/aprod/countable_sum.
apply Series_ext => n.
destruct (encode_inv_nat n); simpl; [ | apply Series_0; auto].
apply Series_ext => m.
destruct (encode_inv_nat m); simpl; auto.
Qed .
Lemma fubini_pos_seriesC_prod_rl :
ex_seriesC h → SeriesC h = SeriesC (λ b, SeriesC (λ a, h (a, b))).
Proof.
intros Hex.
rewrite SeriesC_prod_column //.
rewrite /SeriesC/aprod/countable_sum.
apply Series_ext => n.
destruct (encode_inv_nat n); simpl; last first.
{ rewrite Series_0 //. intros. by case_match. }
apply Series_ext => m.
destruct (encode_inv_nat m); simpl; auto.
Qed.
Lemma fubini_pos_ex_seriesC_prod_ex_lr :
ex_seriesC h → ex_seriesC (λ a, SeriesC (λ b, h (a, b))).
Proof.
intros Hex.
apply ex_seriesC_ex_series.
rewrite /SeriesC/countable_sum.
assert (∀ n,
(from_option
(λ a, Series (λ n0, from_option (λ b, h (a, b)) 0 (encode_inv_nat n0))) 0
(encode_inv_nat n)) =
(Series (λ n0, from_option
(λ a, from_option (λ b, h (a, b)) 0 (encode_inv_nat n0)) 0
(encode_inv_nat n)))) as Haux.
{ intro n. destruct (encode_inv_nat); simpl; auto. by rewrite Series_0. }
setoid_rewrite Haux.
apply (ex_series_row_col
(λ '(n,n0),
from_option (λ a, from_option (λ b, h (a, b)) 0 (encode_inv_nat n0)) 0
(encode_inv_nat n))).
- apply aprod_double_summable in Hex as (r&Hr).
exists r.
intro n.
etrans; [ | apply (Hr (S n))].
right.
rewrite sum_n_shift'.
replace (sum_n (λ k : nat, aprod (0%nat, k)) (S n)) with 0; last first.
{ rewrite (sum_n_ext _ (λ n, 0)).
- rewrite sum_n_const; lra.
- intro; rewrite /aprod //. }
rewrite Rplus_0_r.
apply sum_n_ext; intro m.
rewrite sum_n_shift'.
replace (aprod (S m, 0%nat)) with 0; [ | by rewrite /aprod].
rewrite Rplus_0_r.
apply sum_n_ext; intro l.
rewrite /aprod.
destruct (encode_inv_nat m), (encode_inv_nat l); simpl; auto.
- intros n m.
destruct (encode_inv_nat n), (encode_inv_nat m); simpl; auto; lra.
Qed.
(* TODO: simplify using previous lemma *)
Lemma fubini_pos_ex_seriesC_prod_ex_rl :
ex_seriesC h → ex_seriesC (λ b, SeriesC (λ a, h (a, b))).
Proof.
intros Hex.
apply ex_seriesC_ex_series.
rewrite /SeriesC/countable_sum.
assert (∀ n,
(from_option
(λ b,
Series (λ n0 : nat, from_option (λ a, h (a, b)) 0 (encode_inv_nat n0))) 0
(encode_inv_nat n)) =
(Series (λ n0 : nat,
from_option
(λ b, from_option (λ a, h (a, b)) 0 (encode_inv_nat n0)) 0
(encode_inv_nat n)))) as Haux.
{
intro n. destruct (encode_inv_nat); simpl; auto.
by rewrite Series_0.
}
setoid_rewrite Haux.
apply (ex_series_row_col
(λ '(n,n0),
from_option (λ b, from_option (λ a, h (a, b)) 0 (encode_inv_nat n0)) 0
(encode_inv_nat n))).
- apply aprod_double_summable in Hex as (r&Hr).
exists r.
intro n.
etrans; [ | apply (Hr (S n))].
right.
rewrite fubini_fin_sum.
rewrite sum_n_shift'.
replace (sum_n (λ a : nat, aprod (a, 0%nat)) (S n)) with 0; last first.
{
rewrite (sum_n_ext _ (λ n, 0)).
- rewrite sum_n_const; lra.
- intro; rewrite /aprod.
case_match; auto.
}
rewrite Rplus_0_r.
apply sum_n_ext; intro m.
rewrite sum_n_shift'.
replace (aprod (0%nat, S m)) with 0; [ | by rewrite /aprod].
rewrite Rplus_0_r.
apply sum_n_ext; intro l.
rewrite /aprod.
destruct (encode_inv_nat m), (encode_inv_nat l); simpl; auto.
- intros n m.
destruct (encode_inv_nat n), (encode_inv_nat m); simpl; auto; lra.
Qed.
Lemma ex_seriesC_lmarg a :
ex_seriesC h → ex_seriesC (λ b, h (a, b)).
Proof.
intros Hex.
apply ex_seriesC_ex_series.
rewrite /SeriesC/countable_sum.
apply aprod_double_summable in Hex.
apply DS_n_to_nm in Hex as (r&Hr); last first.
{
intros n m.
rewrite /aprod.
do 4 (case_match; simpl; auto; try lra).
}
apply ex_pos_bounded_series.
- intro n; destruct (encode_inv_nat n); simpl; auto.
lra.
- exists r. intro n.
etrans; [ | apply (Hr (S n) (S (encode_nat a)))].
rewrite sum_n_shift'.
rewrite (sum_n_ext ((λ k : nat, aprod (0%nat, k))) (λ _, 0)); last first.
{
intro; rewrite /aprod //.
}
rewrite sum_n_const Rmult_0_r Rplus_0_r.
etrans; [ | apply partial_sum_elem]; last first.
{
intro.
apply partial_sum_pos.
intro.
rewrite /aprod.
do 4 (case_match; simpl; auto; try lra).
}
rewrite sum_n_shift'.
etrans; last first.
{
apply (Rplus_le_compat_l _ 0).
rewrite /aprod; lra.
}
rewrite Rplus_0_r.
right.
apply sum_n_ext.
intro m.
rewrite /aprod.
rewrite encode_inv_encode_nat.
destruct (encode_inv_nat m); simpl; auto.
Qed.
Lemma ex_seriesC_rmarg b :
ex_seriesC h → ex_seriesC (λ a, h (a, b)).
Proof.
intros Hex.
apply ex_seriesC_ex_series.
rewrite /SeriesC/countable_sum.
apply aprod_double_summable in Hex.
apply DS_n_to_nm in Hex as (r&Hr); last first.
{
intros n m.
rewrite /aprod.
do 4 (case_match; simpl; auto; try lra).
}
apply ex_pos_bounded_series.
- intro n; destruct (encode_inv_nat n); simpl; auto.
lra.
- exists r. intro n.
etrans; [ | apply (Hr (S (encode_nat b)) (S n) )].
rewrite fubini_fin_sum.
rewrite sum_n_shift'.
rewrite (sum_n_ext (λ a : nat, aprod (a, 0%nat)) (λ _, 0)); last first.
{
intro; rewrite /aprod //.
case_match; auto.
}
rewrite sum_n_const Rmult_0_r Rplus_0_r.
etrans; [ | apply partial_sum_elem]; last first.
{
intro.
apply partial_sum_pos.
intro.
rewrite /aprod.
do 4 (case_match; simpl; auto; try lra).
}
rewrite sum_n_shift'.
etrans; last first.
{
apply (Rplus_le_compat_l _ 0).
rewrite /aprod; lra.
}
rewrite Rplus_0_r.
right.
apply sum_n_ext.
intro m.
rewrite /aprod.
rewrite encode_inv_encode_nat.
destruct (encode_inv_nat m); simpl; auto.
Qed.
Lemma seriesC_lmarg_le a :
ex_seriesC h → SeriesC (λ b, h (a, b)) <= SeriesC h.
Proof.
intros Hex.
rewrite fubini_pos_seriesC_prod_rl //.
apply SeriesC_le; [ | eapply fubini_pos_ex_seriesC_prod_ex_rl; eauto].
intro b; split; [real_solver | ].
apply (SeriesC_ge_elem (λ a0, h (a0, b))); [ | apply ex_seriesC_rmarg; auto]; auto.
Qed.
Lemma seriesC_rmarg_le b :
ex_seriesC h → SeriesC (λ a, h (a, b)) <= SeriesC h.
Proof.
intros Hex.
rewrite fubini_pos_seriesC_prod_lr //.
apply SeriesC_le; [ | eapply fubini_pos_ex_seriesC_prod_ex_lr; eauto].
intro a; split; [real_solver | ].
apply (SeriesC_ge_elem (λ b0, h (a, b0))); [ | apply ex_seriesC_lmarg; auto]; auto.
Qed.
Lemma ex_seriesC_prod :
(∀ a, ex_seriesC (λ b, h (a,b))) →
ex_seriesC (λ a, SeriesC (λ b, h (a,b))) →
ex_seriesC h.
Proof.
intros Hex1 Hex2.
assert (ex_series (aprod ∘ σprod)) as Haux; last first.
{
apply ex_seriesC_ex_series.
apply (ex_series_ext _ _ aprod_σprod_countable_sum Haux).
}
apply ds_implies_exseries; auto.
apply ex_series_rows_ds.
- apply aprod_pos.
- intro m. rewrite /aprod.
destruct m as [ | m'].
{
apply ex_pos_bounded_series.
- intro; lra.
- exists 0. intro. rewrite sum_n_const; lra.
}
destruct (encode_inv_nat m') as [ |]; last first.
{
apply ex_pos_bounded_series.
- intro. case_match; lra.
- exists 0. intro. rewrite (sum_n_ext _ (λ _, 0)).
+ rewrite sum_n_const; lra.
+ intro; case_match; auto.
}
specialize (Hex1 a).
apply ex_seriesC_ex_series_inv in Hex1.
rewrite /countable_sum in Hex1.
apply ex_series_incr_1.
eapply (ex_series_ext _ _ _ Hex1). Unshelve.
intro n; simpl.
destruct (encode_inv_nat n); auto.
- apply ex_seriesC_ex_series_inv in Hex2.
rewrite /SeriesC/countable_sum in Hex2.
apply ex_series_incr_1.
eapply (ex_series_ext _ _ _ Hex2). Unshelve.
intro n; simpl.
destruct (encode_inv_nat n); simpl.
+ rewrite (Series_incr_1_aux
(λ k, match k with
| 0%nat => 0
| S n0 => _
end)); auto.
+ rewrite Series_0 //. intro; by case_match.
Qed.
End double.
Section inj.
Context `{Countable A, Countable B}.
Lemma ex_seriesC_inj (g : B->A) (f:A -> R) (Hinj:Inj (=) (=) g):
(∀ a, 0<=f a)->
ex_seriesC f -> ex_seriesC (λ b, f (g b)).
Proof.
intros ? H1.
pose (h:= (λ '(a, b), if bool_decide (g b = a) then f a else 0)).
apply (ex_seriesC_ext (λ z2, SeriesC (λ z1, h (z1, z2)))).
{ rewrite /h.
intros z2.
erewrite SeriesC_ext; first apply SeriesC_singleton_dependent.
simpl. intros; repeat case_bool_decide; by simplify_eq.
}
apply fubini_pos_seriesC_ex_double; rewrite /h.
- intros. by case_bool_decide.
- intros.
destruct (@decide (∃ b, g b = a) (make_decision _)) as [(b&<-)|n].
+ eapply ex_seriesC_ext; last apply (ex_seriesC_singleton b).
intros. simpl. repeat case_bool_decide; subst; by simplify_eq.
+ eapply ex_seriesC_ext; last apply ex_seriesC_0.
intros. rewrite bool_decide_eq_false_2; first done.
intro. apply n. naive_solver.
- eapply (ex_seriesC_le _ f); last done.
intros a.
split; first apply SeriesC_ge_0'.
+ intros. case_bool_decide; naive_solver.
+ destruct (@decide (∃ b, g b = a) (make_decision _)) as [(b&<-)|n].
* erewrite SeriesC_ext; first by erewrite (SeriesC_singleton b).
intros. repeat case_bool_decide; naive_solver.
* erewrite SeriesC_ext; first by rewrite SeriesC_0.
simpl. intros. repeat case_bool_decide; naive_solver.
Qed.
(* A lemma about rearranging SeriesC along an injective function *)
Lemma SeriesC_le_inj (f : B -> R) (h : A -> option B) :
(∀ n, 0 <= f n) →
(forall n1 n2 m, h n1 = Some m -> h n2 = Some m -> n1 = n2) ->
ex_seriesC f →
SeriesC (λ a, from_option f 0 (h a)) <= SeriesC f.
Proof.
intros Hf Hinj Hex.
rewrite {1}/SeriesC/Series.
apply Series_Ext.Lim_seq_le_loc_const.
- by apply SeriesC_ge_0'.
- rewrite /eventually. exists 0%nat.
intros n Hn.
assert (∃ l : list _, (∀ m, m∈l->(∃ k a, (k<=n)%nat /\
(@encode_inv_nat A _ _ k%nat) = Some a /\
h a = Some m)) /\
sum_n (countable_sum (λ a : A, from_option f 0 (h a))) n <=
SeriesC (λ a, if bool_decide(a ∈ l) then f a else 0)
) as H'; last first.
{ destruct H' as [?[??]].
etrans; first exact.
apply SeriesC_le'; try done.
- intros. case_bool_decide; try lra. apply Hf.
- apply ex_seriesC_list.
}
induction n.
+ destruct (@encode_inv_nat A _ _ 0%nat) eqn:Ha.
* destruct (h a) eqn : Hb.
-- exists [b]. split.
++ intros. exists 0%nat, a.
repeat split; try lia; try done.
rewrite Hb. f_equal. set_solver.
++ rewrite sum_O. rewrite /countable_sum.
rewrite Ha. simpl. rewrite Hb. simpl.
erewrite SeriesC_ext.
** erewrite SeriesC_singleton_dependent. done.
** intro. simpl.
repeat case_bool_decide; set_solver.
-- exists []. split.
++ intros; set_solver.
++ rewrite sum_O. rewrite /countable_sum.
rewrite Ha. simpl. rewrite Hb. simpl.
rewrite SeriesC_0; intros; lra.
* exists []. split.
++ intros; set_solver.
++ rewrite sum_O. rewrite /countable_sum.
rewrite Ha. simpl.
rewrite SeriesC_0; intros; lra.
+ assert (0<=n)%nat as Hge0.
* lia.
* specialize (IHn Hge0) as [l[H1 H2]].
destruct (@encode_inv_nat A _ _ (S n)%nat) eqn:Ha.
-- destruct (h a) eqn : Hb.
++ exists (b::l). split.
** intros. set_unfold.
destruct H3; subst.
--- exists (S n), a. split; try lia. split; done.
--- specialize (H1 m H3).
destruct H1 as [?[?[?[??]]]].
exists x, x0. split; try lia. by split.
** rewrite sum_Sn. rewrite {2}/countable_sum.
rewrite Ha. simpl. rewrite Hb. simpl.
rewrite (SeriesC_ext _ (λ x, (if bool_decide (x=b) then f b else 0) +
if bool_decide (x∈l) then f x else 0
)); last first.
{ intros.
case_bool_decide.
- set_unfold. destruct H3.
+ case_bool_decide; last done.
case_bool_decide.
* subst. specialize (H1 b H5).
destruct H1 as [?[?[?[??]]]].
rewrite -H6 in Hb.
assert (a = x0).
{ eapply Hinj; try done. rewrite Hb. done. }
subst. exfalso.
rewrite -H3 in Ha. assert (x≠ (S n)) by lia.
apply H7. by eapply encode_inv_nat_some_inj.
* subst. lra.
+ case_bool_decide.
{ subst. specialize (H1 b H3) as [?[?[?[??]]]].
assert (x ≠ S n) by lia.
exfalso. apply H6. eapply encode_inv_nat_some_inj; try done.
rewrite Ha H4. f_equal.
by eapply Hinj.
}
case_bool_decide; try done. lra.
- repeat case_bool_decide.
+ set_solver.
+ set_solver.
+ set_solver.
+ lra.
}
rewrite SeriesC_plus; last first.
{ by apply ex_seriesC_filter_pos. }
{ by apply ex_seriesC_singleton. }
rewrite Rplus_comm. rewrite SeriesC_singleton.
trans ((sum_n (countable_sum (λ a0 : A, from_option f 0 (h a0))) n) + f b); try lra.
done.
++ exists l. split.
** intros. specialize (H1 _ H3) as [?[?[?[??]]]].
exists x, x0. repeat split; try done. lia.
** rewrite sum_Sn. rewrite {2}/countable_sum. rewrite Ha. simpl.
rewrite Hb. simpl. etrans; last exact.
by rewrite plus_zero_r.
-- exists l. split.
++ intros. specialize (H1 _ H3) as [?[?[?[??]]]].
exists x, x0. repeat split; try done. lia.
++ rewrite sum_Sn. rewrite {2}/countable_sum. rewrite Ha. simpl.
etrans; last exact.
by rewrite plus_zero_r.
Qed.
End inj.
Lemma SeriesC_translate f loc (fpos : ∀ z, 0 <= f z) (fex : ex_seriesC f) :
(SeriesC (λ z : Z, f (z + loc)) = SeriesC f)%Z.
Proof.
opose proof (SeriesC_le_inj f (λ z, Some (z + loc))%Z _ _ _) as lb => //.
{ intros ??? h h'. inversion h ; inversion h'. lia. }
simpl in lb.
opose proof (SeriesC_le_inj (λ z, f (z + loc))%Z (λ z, Some (z - loc))%Z _ _ _) as ub => //.
{ intros ??? h h'. inversion h ; inversion h'. lia. }
1: apply ex_seriesC_inj => //.
{ intros ?? h. inversion h. lia. }
simpl in ub.
setoid_rewrite Z.sub_simpl_r in ub. apply Rle_antisym => //.
Qed.
Section Inj_finite.
Lemma SeriesC_filter_finite_1 `{Countable A} (M:nat) (f:A -> R) (g: fin M -> R) h:
Inj eq eq h -> (0 < M)%nat -> (∀ a: A, 0 <= f a <= 1) -> (∀ b: fin M, 0 <= g b <= 1) ->
(∀ (a : A) (b : fin M), a = h b → f a <= g b) ->
SeriesC (λ a : A, if bool_decide (∃ y : fin M, a = h y) then f a else 0) <= SeriesC g.
Proof.
intros Hinj Hineq Hf Hg Hfg.
rewrite {1}/SeriesC. apply series_bounded.
{ intros. apply countable_sum_ge_0. intros; case_bool_decide; naive_solver. }
2:{ eapply ex_seriesC_ex_series_inv, ex_seriesC_ext; last eapply ex_seriesC_list.
instantiate (2:= h <$> enum (fin M)).
intros. case_bool_decide as H1; case_bool_decide as H2; try done.
- exfalso.
apply H2. destruct H1. subst. apply list_elem_of_fmap_2, elem_of_enum.
- exfalso. apply H1. rewrite list_elem_of_fmap in H2. destruct H2 as [y[??]].
naive_solver.
}
intros n.
cut (∃ l', NoDup l' /\ (∀ y, y ∈ l' <-> (∃ x, x = h y /\ (encode_nat x <= n)%nat)) /\
sum_n (countable_sum (λ a : A, if bool_decide (∃ y : fin M, a = h y) then f a else 0)) n <= SeriesC (λ x, if bool_decide (x ∈ l') then g x else 0)
).
{ intros [?[?[??]]]. etrans; first exact. apply SeriesC_filter_leq; last apply ex_seriesC_finite.
intros; naive_solver.
}
induction n.
- rewrite sum_O /countable_sum. destruct (encode_inv_nat _) eqn:H1; simpl.
+ case_bool_decide as H2.
* destruct H2 as [y?].
exists [y].
repeat split.
-- repeat constructor. set_solver.
-- intros. exists a. split; first set_solver.
apply encode_inv_Some_nat in H1. lia.
-- intros [?[??]].
subst. assert (encode_nat (h y0) = 0%nat) by lia.
apply encode_inv_Some_nat in H1. rewrite -H1 in H0.
apply encode_nat_inj in H0. apply Hinj in H0. set_solver.
-- subst. erewrite SeriesC_ext.
{ erewrite SeriesC_singleton_dependent. by apply Hfg. }
intros. repeat case_bool_decide; set_solver.
* exists []. repeat split.
-- constructor.
-- set_solver.
-- intros [? [??]]. exfalso. apply H2. apply encode_inv_Some_nat in H1.
assert (encode_nat x = 0%nat) by lia. rewrite -H1 in H4. apply encode_nat_inj in H4; subst.
naive_solver.
-- apply SeriesC_ge_0'. intros. case_bool_decide; naive_solver.
+ exists []. repeat split.
-- constructor.
-- set_solver.
-- intros [?[??]]. assert (encode_nat x = 0%nat) by lia. rewrite -H3 in H1.
by rewrite encode_inv_encode_nat in H1.
-- apply SeriesC_ge_0'. intros. case_bool_decide; naive_solver.
- destruct IHn as [l'[Hnd[H1 H2]]].
rewrite sum_Sn /countable_sum. destruct (encode_inv_nat _) eqn:H3; simpl.
+ case_bool_decide as H4.
* destruct H4 as [y?].
exists (y::l'). repeat split.
-- constructor; last done. move /H1. intros [?[??]]. subst.
apply encode_inv_Some_nat in H3. lia.
-- move /elem_of_cons. intros [->|?].
++ exists a. split; first done. apply encode_inv_Some_nat in H3. lia.
++ subst. rewrite H1 in H4. naive_solver.
-- intros [?[??]]. subst.
rewrite Nat.le_succ_r in H5. destruct H5.
++ apply list_elem_of_further. rewrite H1.
eexists _; by split.
++ apply encode_inv_Some_nat in H3. rewrite -H3 in H0. apply encode_nat_inj in H0.
apply Hinj in H0. set_solver.
-- rewrite (SeriesC_ext _ (λ x : fin M, (if bool_decide (x ∈ l') then g x else 0)+if bool_decide (x = y) then g x else 0)).
++ rewrite SeriesC_plus; try apply ex_seriesC_finite.
apply Rplus_le_compat; first done.
rewrite SeriesC_singleton_dependent.
by apply Hfg.
++ intros n'. repeat case_bool_decide; try done; try lra; subst.
** rewrite H1 in H5. destruct H5 as [?[??]]. subst.
apply encode_inv_Some_nat in H3. lia.
** set_solver.
** set_solver.
** set_solver.
** set_solver.
* exists l'. repeat split; try done.
-- intros. naive_solver.
-- intros [?[??]]. rewrite H1. subst. eexists _; split; first done.
rewrite Nat.le_succ_r in H5. destruct H5; try lia.
exfalso. apply H4. apply encode_inv_Some_nat in H3. rewrite -H3 in H0.
apply encode_nat_inj in H0. naive_solver.
-- rewrite plus_zero_r. done.
+ exists l'. repeat split; try done.
* intros. naive_solver.
* elim. intros ?[??]. subst. rewrite H1. eexists _; split; first done.
rewrite Nat.le_succ_r in H4. destruct H4; first done.
rewrite -H0 in H3. by rewrite encode_inv_encode_nat in H3.
* by rewrite plus_zero_r.
Qed.
Lemma SeriesC_filter_finite_1_bounds `{Countable A} (M:nat) (f:A -> R) (g: fin M -> R) h r:
Inj eq eq h -> (0 < M)%nat -> (0<r)-> (∀ a: A, 0 <= f a <= r) -> (∀ b: fin M, 0 <= g b <= r) ->
(∀ (a : A) (b : fin M), a = h b → f a <= g b) ->
SeriesC (λ a : A, if bool_decide (∃ y : fin M, a = h y) then f a else 0) <= SeriesC g.
Proof.
intros Hinj Hm Hr Hf Hg Hfg.
apply (Rmult_le_reg_r (/r)).
{ rewrite -Rdiv_1_l. apply Rdiv_lt_0_compat; lra. }
rewrite -!SeriesC_scal_r.
erewrite (SeriesC_ext _ (λ x : A, (if bool_decide (∃ y : fin M, x = h y) then (λ x, f x / r) x else 0))); last first.
{ intros. case_bool_decide; lra. }
apply SeriesC_filter_finite_1; try done.
- intros; split.
+ apply Rcomplements.Rdiv_le_0_compat; try lra. naive_solver.
+ rewrite Rcomplements.Rle_div_l; last naive_solver. rewrite Rmult_1_l. naive_solver.
- intros; split.
+ apply Rcomplements.Rdiv_le_0_compat; try lra. naive_solver.
+ rewrite Rcomplements.Rle_div_l; last naive_solver. rewrite Rmult_1_l. naive_solver.
- intros. rewrite Rdiv_def. apply Rmult_le_compat_r; last naive_solver.
rewrite -Rdiv_1_l. apply Rcomplements.Rdiv_le_0_compat; try lra.
Qed.
Lemma SeriesC_filter_finite_1' (N M:nat) (f:fin N -> R) (g: fin M -> R) h:
Inj eq eq h -> (0 < M <= N)%nat -> (∀ a: fin N, 0 <= f a <= 1) -> (∀ b: fin M, 0 <= g b <= 1) ->
(∀ (a : fin N) (b : fin M), a = h b → f a <= g b) ->
SeriesC (λ a : fin N, if bool_decide (∃ y : fin M, a = h y) then f a else 0) <= SeriesC g.
Proof.
intros Hinj Hineq Hf Hg Hfg.
apply SeriesC_filter_finite_1; try done.
lia.
Qed.
Lemma SeriesC_filter_finite_2 (N M:nat) (f:fin N -> R) h:
Inj eq eq h -> (0 < M <= N)%nat -> (∀ a: fin N, 0 <= f a <= 1) ->
SeriesC (λ a : fin N, if bool_decide (∃ y : fin M, a = h y) then 0 else f a) <= (N-M)%nat.
Proof.
intros Hinj Hineq Hf. rewrite minus_INR; last naive_solver.
rewrite Rcomplements.Rle_minus_r.
replace (INR M) with (SeriesC (λ a : fin N, if bool_decide (∃ y : fin M, a = h y) then 1 else 0)).
- rewrite -SeriesC_plus; try apply ex_seriesC_finite.
trans (SeriesC (λ _:fin N, 1)).
+ apply SeriesC_le; last apply ex_seriesC_finite.
intros n; case_bool_decide; try lra.
rewrite Rplus_0_r; naive_solver.
+ rewrite SeriesC_finite_mass fin_card. lra.
- replace (INR M) with (SeriesC (λ _:fin M, 1)); last (rewrite SeriesC_finite_mass fin_card; lra).
apply Rle_antisym.
+ apply SeriesC_filter_finite_1'; try done; intros; lra.
+ etrans; last first.
* eapply SeriesC_le_inj; last apply ex_seriesC_finite.
-- intros. case_bool_decide; lra.
-- intros ???. instantiate (2 := (λ x, (Some (h x)))). simpl.
intros H1 H2. rewrite -H1 in H2. inversion H2. by apply Hinj.
* apply SeriesC_le; last apply ex_seriesC_finite.
intros n. split; first lra.
simpl. case_bool_decide; first done.
exfalso; naive_solver.
Qed.
Lemma SeriesC_fin_in_set (N : nat) (ns : gset nat):
(forall x, x ∈ ns -> (x < S N)%nat ) ->
(SeriesC (λ x : fin (S N), if bool_decide (fin_to_nat x ∈ ns) then 1 else 0) = size ns).
Proof.
revert ns.
epose proof (set_ind
(λ (s : gset nat), (forall x, x ∈ s -> ( x < S N)%nat ) ->
(SeriesC (λ x : fin (S N), if bool_decide (fin_to_nat x ∈ s) then 1 else 0) = size s))).
apply H.
- solve_proper.
- intro Hlt.
rewrite size_empty.
apply SeriesC_0.
intro.
rewrite bool_decide_eq_false_2; auto.
set_solver.
- intros x ns HnElem Hseries Hlt.
rewrite size_union; [ | set_solver].
erewrite SeriesC_ext; last first.
+ intros.
erewrite bool_decide_ext; [ | apply elem_of_union ].
done.
Unshelve. solve_decision.
+ etrans.
* symmetry.
eapply is_seriesC_filter_union.
2: { apply SeriesC_correct, ex_seriesC_finite. }
intro; simpl; lra.
* rewrite size_singleton plus_INR /=.
assert (x < S N)%nat as Hxlt.
{
apply Hlt. set_solver.
}
rewrite {1}(SeriesC_ext _ (λ n, if bool_decide (n = (nat_to_fin Hxlt)) then 1 else 0));
last first.
{
intro n.
erewrite bool_decide_ext; [ | apply elem_of_singleton ].
case_bool_decide as Hnx ; simplify_eq.
- rewrite bool_decide_eq_true_2; auto.
by rewrite nat_to_fin_to_nat.
- rewrite bool_decide_eq_false_2; auto.
intros ->.
apply Hnx.
by rewrite fin_to_nat_to_fin.
}
rewrite SeriesC_singleton Hseries; [ | intros; apply Hlt; set_solver ].
rewrite SeriesC_0; [lra |].
intros.
rewrite bool_decide_eq_false_2; auto.
set_solver.
Unshelve. solve_decision.
Qed.
Lemma SeriesC_fin_in_set' (N : nat) (ns : gset nat) v:
(forall x, x ∈ ns -> (x < S N)%nat ) ->
(SeriesC (λ x : fin (S N), if bool_decide (fin_to_nat x ∈ ns) then v else 0) = v* size ns).
Proof.
erewrite (SeriesC_ext _ (λ x : fin (S N), v* if bool_decide (fin_to_nat x ∈ ns) then 1 else 0)).
- intros. rewrite SeriesC_scal_l.
by rewrite SeriesC_fin_in_set.
- intros.
case_bool_decide; lra.
Qed.
Lemma SeriesC_fin_not_in_set (N : nat) (ns : gset nat) :
(forall x, x ∈ ns -> (x < S N)%nat ) ->
(SeriesC (λ x : fin (S N), if bool_decide (fin_to_nat x ∉ ns) then 1 else 0) = (N + 1 - size ns))%R.
Proof.
intros Hlt.
apply Req_minus_r.
rewrite -(SeriesC_fin_in_set N); auto.
rewrite -SeriesC_plus; [ | apply ex_seriesC_finite | apply ex_seriesC_finite ].
erewrite (SeriesC_ext _ (λ _, 1)); last first.
{
intros.
case_bool_decide; case_bool_decide.
- set_solver.
- lra.
- lra.
- set_solver.
}
rewrite SeriesC_finite_mass fin_card S_INR.
lra.
Qed.
Lemma SeriesC_fin_not_in_set' (N : nat) (ns : gset nat) v:
(forall x, x ∈ ns -> (x < S N)%nat ) ->
(SeriesC (λ x : fin (S N), if bool_decide (fin_to_nat x ∉ ns) then v else 0) = v*(N + 1 - size ns))%R.
Proof.
erewrite (SeriesC_ext _ (λ x : fin (S N), v* if bool_decide (fin_to_nat x ∉ ns) then 1 else 0)).
- intros. rewrite SeriesC_scal_l.
by rewrite SeriesC_fin_not_in_set.
- intros.
case_bool_decide; lra.
Qed.
End Inj_finite.
Section gmap.
(* very specialized lemmas for elton *)
Lemma ex_seriesC_gmap_insert `{Countable X} `{Countable Y} l g f:
(∀ x, 0<= f x) -> (∀ x, 0 <= g x) ->
ex_seriesC f ->
ex_seriesC g ->
ex_seriesC (λ (m : gmap X Y), match m!!l with
| Some z => f (delete l m) * g z
| None => 0
end
).
Proof.
intros H1 H2 H3 H4.
pose (f' := (λ '(m, z),
match z with
| Some z => f m * g z
| None => 0
end
)).
pose (g' := (λ (m:gmap X Y), (delete l m, m!!l))).
apply (ex_seriesC_ext (λ m, f' (g' m))); first done.
apply ex_seriesC_inj.
{ intros ??.
rewrite /g'.
intros. simplify_eq.
apply map_eq.
intros i.
destruct (decide (i=l)); subst; simplify_map_eq; first done.
erewrite <-lookup_delete_ne; last done.
erewrite <-(lookup_delete_ne y); last done.
by f_equal.
}
{ intros.
rewrite /f'.
case_match.
subst.
case_match; real_solver.
}
rewrite /f'.
apply ex_seriesC_prod.
- intros. case_match; real_solver.
- intros a.
apply (ex_seriesC_le _ (λ b, f a * from_option g 0 b)).
{ intros. case_match; real_solver. }
apply ex_seriesC_scal_l.
apply ex_seriesC_from_option; naive_solver.
- apply (ex_seriesC_le _ (λ a, SeriesC (λ b, f a * from_option g 0 b))).
{ intros. split.
- apply SeriesC_ge_0'. real_solver.
- right.
apply SeriesC_ext.
intros. case_match; real_solver.
}
setoid_rewrite SeriesC_scal_l.
by apply ex_seriesC_scal_r.
Qed.
Lemma SeriesC_gmap_insert_le_1 `{Countable X} `{Countable Y} f g l:
(∀ x, 0<= f x) -> (∀ x, 0 <= g x) ->
ex_seriesC f ->
ex_seriesC g ->
SeriesC f<=1 ->
SeriesC (g) <=1 ->
SeriesC (λ (m : gmap X Y), match m!!l with
| Some z => f (delete l m) * g z
| None => 0
end
) <= 1.
Proof.
intros H1 H2 H3 H4 H5 H6.
pose (f' := (λ '(m, z),f m * g z
)).
pose (g' := (λ (m:gmap X Y), match m!!l with
| Some z => Some (delete l m, z)
| None => None
end
)).
erewrite (SeriesC_ext _ (λ m, from_option f' 0 (g' m))); last first.
{ intros. rewrite /g'/f'. by case_match. }
etrans; first apply SeriesC_le_inj.
- intros. rewrite /f'.
case_match.
real_solver.
- rewrite /g'.
intros. repeat case_match; simplify_eq.
apply map_eq.
intros i.
destruct (decide (i=l)); subst; simplify_map_eq; first done.
erewrite <-lookup_delete_ne; last done.
erewrite <-(lookup_delete_ne n2); last done.
by f_equal.
- rewrite /f'.
apply ex_seriesC_prod.
+ real_solver.
+ intros.
by apply ex_seriesC_scal_l.
+ setoid_rewrite SeriesC_scal_l.
by apply ex_seriesC_scal_r.
- rewrite /f'.
rewrite fubini_pos_seriesC_prod_lr; last first.
+ apply ex_seriesC_prod.
* real_solver.
* intros. by apply ex_seriesC_scal_l.
* setoid_rewrite SeriesC_scal_l.
by apply ex_seriesC_scal_r.
+ real_solver.
+ setoid_rewrite (SeriesC_scal_l _ (f _)).
setoid_rewrite (SeriesC_scal_r).
replace (1) with (1*1) by lra.
apply Rmult_le_compat; try done; by apply SeriesC_ge_0'.
Qed.
End gmap.
Ltac series_solver_partial :=
match goal with
| |- 0 <= SeriesC _ => apply SeriesC_ge_0'
| |- SeriesC _ = SeriesC _ => apply SeriesC_ext
end.
Ltac series := repeat (series_solver_partial || real_solver_partial).