(* Copyright 2012-2015 by Adam Petcher.				* * Use of this source code is governed by the license described	* * in the LICENSE file at the root of the source tree.		*)
(* Definitions of asymptotic notions such as polynomial and negligible functions, and related theory. *)
Set Implicit Arguments.
Definition polynomial (f : nat -> nat) :=
exists x c1 c2, forall n,
(f n <= c1 * expnat n x + c2)%nat.
Definition polynomial_nz(f : nat -> nat) :=
exists x c1 c2,
x > 0 /\ c1 > 0 /\ c2 > 0 /\
forall n,
(f n <= c1 * expnat n x + c2)%nat.
intuition.
unfold polynomial, polynomial_nz in *.
do 3 (destruct H).
exists (S x).
exists (S x0).
exists (x0 + S x1).
intuition.
rewrite H.
rewrite plus_assoc.
eapply plus_le_compat; intuition.
simpl.
destruct (eq_nat_dec x 0).
subst.
simpl.
repeat rewrite mult_1_r.
rewrite <- plus_0_l at 1.
eapply plus_le_compat; intuition.
rewrite <- plus_0_l at 1.
rewrite <- plus_0_r at 1.
eapply plus_le_compat; intuition.
eapply plus_le_compat; intuition.
eapply mult_le_compat; intuition.
destruct (eq_nat_dec n 0); subst.
rewrite expnat_0;
omega.
rewrite <- mult_1_l at 1.
eapply mult_le_compat; intuition.
Qed.
intuition.
apply polynomial_nz_equiv in H.
apply polynomial_nz_equiv in H0.
unfold polynomial, polynomial_nz in *.
Ltac des :=
match goal with
| [H : exists _, _ |- _] => destruct H
end.
repeat des.
intuition.
exists (max x2 x).
exists (x3 + x0).
exists (x4 + x1).
intuition.
eapply le_trans.
eapply plus_le_compat.
eapply H6; trivial.
eapply H7; trivial.
rewrite mult_plus_distr_r.
repeat rewrite plus_assoc.
eapply plus_le_compat; trivial.
rewrite plus_comm.
rewrite plus_assoc.
eapply plus_le_compat; trivial.
rewrite plus_comm.
eapply plus_le_compat;
eapply mult_le_compat; intuition.
eapply expnat_exp_le; intuition.
eapply expnat_exp_le; intuition.
Qed.
intuition.
unfold polynomial.
exists 0.
exists 0.
exists c.
intuition.
Qed.
unfold polynomial.
intuition.
exists 1.
exists 1.
exists 0.
intuition.
simpl.
omega.
Qed.
intros f1 f2 H H0.
apply polynomial_nz_equiv in H.
apply polynomial_nz_equiv in H0.
unfold polynomial, polynomial_nz in *.
repeat des.
intuition.
exists (x + x2).
exists (3 * (x3 * x0 * x4 * x1)).
exists (x4 * x1).
intros n.
eapply le_trans.
eapply mult_le_compat.
eapply H6; intuition.
eapply H7; intuition.
repeat rewrite mult_plus_distr_l.
repeat rewrite mult_plus_distr_r.
rewrite plus_assoc.
eapply plus_le_compat; trivial.
rewrite expnat_plus.
simpl.
rewrite plus_0_r.
repeat rewrite mult_plus_distr_r.
rewrite plus_assoc.
eapply plus_le_compat.
eapply plus_le_compat.
rewrite (mult_comm (expnat n x)).
repeat rewrite mult_assoc.
eapply mult_le_compat. 2: reflexivity.
rewrite mult_comm.
rewrite mult_assoc.
eapply mult_le_compat. 2: reflexivity.
rewrite <- mult_1_r at 1.
rewrite <- mult_1_r at 1.
eapply mult_le_compat. 2: auto with zarith.
eapply mult_le_compat. 2: auto with zarith.
rewrite mult_comm.
reflexivity.
destruct (eq_nat_dec n 0); subst.
repeat rewrite expnat_0.
simpl.
repeat rewrite mult_0_r.
reflexivity.
trivial.
trivial.
rewrite (mult_comm (expnat n x)).
repeat rewrite mult_assoc.
eapply mult_le_compat; trivial.
rewrite <- mult_1_r at 1.
eapply mult_le_compat; trivial.
rewrite <- mult_1_r at 1.
eapply mult_le_compat; trivial.
rewrite mult_comm.
eapply mult_le_compat; trivial.
rewrite <- mult_1_l at 1.
eapply mult_le_compat; trivial.
eapply expnat_ge_1.
omega.
destruct (eq_nat_dec n 0); subst.
repeat rewrite expnat_0.
simpl.
repeat rewrite mult_0_r.
intuition.
trivial.
trivial.
rewrite (mult_comm (expnat n x)).
repeat rewrite mult_assoc.
rewrite <- mult_1_r at 1.
eapply mult_le_compat; trivial.
rewrite <- mult_assoc.
rewrite (mult_comm (expnat n x2)).
rewrite mult_assoc.
eapply mult_le_compat; trivial.
eapply mult_le_compat; trivial.
rewrite <- mult_1_r at 1.
eapply mult_le_compat; trivial.
rewrite <- mult_1_r at 1.
eapply mult_le_compat; trivial.
eapply expnat_ge_1.
omega.
Qed.
Local Open Scope rat_scope.
Definition negligible(f : nat -> Rat) :=
forall c, exists n, forall x (pf_nz : nz x),
x > n ->
~ ((1 / expnat x c) <= f x)%rat.
intuition.
unfold negligible in *.
intuition.
edestruct H.
econstructor.
intuition.
eapply H1.
eauto.
rewrite H3.
rewrite <- H0.
intuition.
Qed.
intuition.
unfold negligible in *.
intuition.
edestruct H0.
econstructor.
intuition.
eapply H1.
eauto.
rewrite H3.
eauto.
Qed.
unfold negligible in *.
intuition.
destruct (H (S c)).
destruct (H0 (S c)).
exists (max 1 (max x x0)).
intuition.
apply Nat.max_lub_lt_iff in H3.
intuition.
assert (1 / expnat x1 c <= 2/1 * (maxRat (f1 x1) (f2 x1)))%rat.
eapply leRat_trans.
eapply H4.
eapply ratAdd_2_ratMax.
assert (1 / expnat x1 (S c) <= RatIntro 1 (posnatMult (pos 2) (pos (expnat x1 c))))%rat.
eapply leRat_terms; intuition.
unfold natToPosnat, posnatToNat, posnatMult.
eapply expnat_double_le.
omega.
unfold maxRat in *.
case_eq (bleRat (f1 x1) (f2 x1)); intuition.
rewrite H8 in H3.
eapply H2.
eapply le_lt_trans.
eapply Max.le_max_r.
eauto.
rewrite H7.
rewrite rat_mult_den.
rewrite H3.
rewrite <- ratMult_assoc.
rewrite <- ratMult_num_den.
rewrite num_dem_same_rat1.
rewrite ratMult_1_l.
intuition.
unfold posnatMult, natToPosnat, posnatToNat.
omega.
rewrite H8 in H3.
eapply H1.
eapply le_lt_trans.
eapply Max.le_max_l.
eauto.
rewrite H7.
rewrite rat_mult_den.
rewrite H3.
rewrite <- ratMult_assoc.
rewrite <- ratMult_num_den.
rewrite num_dem_same_rat1.
rewrite ratMult_1_l.
intuition.
unfold posnatMult, natToPosnat, posnatToNat.
omega.
Qed.
(* We need several facts about arithmetic to show that an inverse exponential function is negligible. *)
Local Open Scope nat_scope.

Theorem double_log_plus_3_le_h :
forall y x,
y = Nat.log2 x ->
y >= 4 ->
2 * y + 3 <= x.