Theory Theta_Nullwert
section ‹The theta nullwert functions›
theory Theta_Nullwert
imports "Sum_Of_Squares_Count.Sum_Of_Squares_Count" Jacobi_Triple_Product
begin
text ‹
The theta nullwert function (nullwert being German for ``zero value'') are the
four functions $\vartheta_{xy}(z; \tau)$ with $z = 0$. However, they are very commonly
denoted in terms of the nome instead, corresponding to $\vartheta_{xy}(w, q)$ with $w = 1$.
It is easy to see that $\vartheta_{11}(0; \tau) = \vartheta_{11}(1, q)$ is identically zero
and therefore uninteresting. The remaining three functions $\vartheta_{10}(0, q)$,
$\vartheta_{00}(0, q)$, and $\vartheta_{01}(0, q)$ are denoted $\vartheta_2(q)$,
$\vartheta_3(q)$, and $\vartheta_4(q)$.
It is also not hard to see that in fact $\vartheta_4(q) = \vartheta_3(-q)$, but we still
introduce separate notation for $\vartheta_4$ since it is very commonly used in the literature.
›
lemma jacobi_theta_nome_11_1_left [simp]: "jacobi_theta_nome_11 1 q = 0"
using jacobi_theta_nome_minus_same[of q] by (auto simp: jacobi_theta_nome_11_def)
abbreviation jacobi_theta_nw_10 :: "'a :: {real_normed_field, banach, ln} ⇒ 'a" where
"jacobi_theta_nw_10 q ≡ jacobi_theta_nome_10 1 q"
abbreviation jacobi_theta_nw_00 :: "'a :: {real_normed_field, banach} ⇒ 'a" where
"jacobi_theta_nw_00 q ≡ jacobi_theta_nome_00 1 q"
abbreviation jacobi_theta_nw_01 :: "'a :: {real_normed_field, banach} ⇒ 'a" where
"jacobi_theta_nw_01 q ≡ jacobi_theta_nome_01 1 q"
bundle jacobi_theta_nw_notation
begin
notation jacobi_theta_nw_10 ("θ⇩2")
notation jacobi_theta_nw_00 ("θ⇩3")
notation jacobi_theta_nw_01 ("θ⇩4")
end
bundle no_jacobi_theta_nw_notation
begin
no_notation jacobi_theta_nw_10 ("θ⇩2")
no_notation jacobi_theta_nw_00 ("θ⇩3")
no_notation jacobi_theta_nw_01 ("θ⇩4")
end
unbundle jacobi_theta_nw_notation
lemma jacobi_theta_nw_10_0 [simp]: "θ⇩2 0 = 0"
and jacobi_theta_nw_00_0 [simp]: "θ⇩3 0 = 1"
and jacobi_theta_nw_01_0 [simp]: "θ⇩4 0 = 1"
by simp_all
lemma jacobi_theta_nw_01_conv_00: "θ⇩4 q = θ⇩3 (-q)"
by (simp add: jacobi_theta_nome_01_conv_00)
lemma jacobi_theta_nw_10_of_real:
"y ≥ 0 ⟹ θ⇩2 (complex_of_real y) = of_real (θ⇩2 y)"
and jacobi_theta_nw_00_of_real: "θ⇩3 (of_real x) = of_real (θ⇩3 x)"
and jacobi_theta_nw_01_of_real: "θ⇩4 (of_real x) = of_real (θ⇩4 x)"
by (simp_all flip: jacobi_theta_nome_10_complex_of_real jacobi_theta_nome_00_of_real
jacobi_theta_nome_01_of_real)
lemma jacobi_theta_nw_10_cnj:
"(Im q = 0 ⟹ Re q ≥ 0) ⟹ θ⇩2 (cnj q) = cnj (θ⇩2 q)"
and jacobi_theta_nw_00_cnj: "θ⇩3 (cnj q) = cnj (θ⇩3 q)"
and jacobi_theta_nw_01_cnj: "θ⇩4 (cnj q) = cnj (θ⇩4 q)"
by (simp_all flip: jacobi_theta_nome_10_cnj jacobi_theta_nome_00_cnj jacobi_theta_nome_01_cnj)
text ‹
The nullwerte have the following definitions as infinite sums:
\begin{align*}
\vartheta_2(q) &= \sum\limits_{-\infty}^\infty q^{(n+\frac{1}{2})^2}\\
\vartheta_3(q) &= \sum\limits_{-\infty}^\infty q^{n^2}\\
\vartheta_4(q) &= \sum\limits_{-\infty}^\infty (-1)^n q^{n^2}
\end{align*}
›
lemma has_sum_jacobi_theta_nw_10_complex:
assumes "norm (q :: complex) < 1"
shows "((λn. q powr ((of_int n + 1 / 2) ^ 2)) has_sum θ⇩2 q) UNIV"
proof (cases "q = 0")
case [simp]: False
show ?thesis
using has_sum_jacobi_theta_nome_10[of q 1] assms by simp
qed auto
lemma has_sum_jacobi_theta_nw_10_real:
assumes "q ∈ {0<..<1::real}"
shows "((λn. q powr ((of_int n + 1 / 2) ^ 2)) has_sum θ⇩2 q) UNIV"
proof (cases "q = 0")
case [simp]: False
show ?thesis
using has_sum_jacobi_theta_nome_10[of q 1] assms by simp
qed auto
lemma has_sum_jacobi_theta_nw_00:
assumes "norm q < 1"
shows "((λn. q powi (n ^ 2)) has_sum θ⇩3 q) UNIV"
using has_sum_jacobi_theta_nome_00[of q 1] assms by simp
lemma has_sum_jacobi_theta_nw_01:
assumes "norm q < 1"
shows "((λn. (-1) powi n * q powi (n ^ 2)) has_sum θ⇩4 q) UNIV"
using has_sum_jacobi_theta_nome_01[of q 1] assms by simp
text ‹
The theta nullwert functions do not vanish (except for ‹θ⇩2(0) = 0›).
›
lemma jacobi_theta_00_nw_nonzero_complex: "norm (q::complex) < 1 ⟹ θ⇩3 q ≠ 0"
by (simp add: jacobi_theta_nome_00_def jacobi_theta_nome_1_left_nonzero_complex)
lemma jacobi_theta_01_nw_nonzero_complex: "norm (q::complex) < 1 ⟹ θ⇩4 q ≠ 0"
by (simp add: jacobi_theta_nw_01_conv_00 jacobi_theta_00_nw_nonzero_complex)
lemma jacobi_theta_10_nw_nonzero_complex:
assumes "q ≠ 0" "norm (q::complex) < 1"
shows "θ⇩2 q ≠ 0"
using jacobi_theta_nome_q_q_nonzero_complex[of q] assms
by (auto simp: jacobi_theta_nome_10_def)
lemma jacobi_theta_00_nw_nonzero_real: "¦q::real¦ < 1 ⟹ θ⇩3 q ≠ 0"
and jacobi_theta_01_nw_nonzero_real: "¦q::real¦ < 1 ⟹ θ⇩4 q ≠ 0"
and jacobi_theta_10_nw_nonzero_real: "q ∈ {0..<1} ⟹ q ≠ 0 ⟹ θ⇩2 q ≠ 0"
using jacobi_theta_00_nw_nonzero_complex[of "of_real q"]
jacobi_theta_01_nw_nonzero_complex[of "of_real q"]
jacobi_theta_10_nw_nonzero_complex[of "of_real q"]
by (simp_all add: jacobi_theta_nw_00_of_real jacobi_theta_nw_01_of_real
jacobi_theta_nw_10_of_real)
subsection ‹The Maclaurin series of $\vartheta_3$ and $\vartheta_4$›
text ‹
It is easy to see from the above infinite sums that $\vartheta_3(q)$ and $\vartheta_4(q)$ have the
Maclaurin series
\[1 + 2\sum_{n=1}^\infty [\exists i.\ n = i^2] c^n q^n\]
for $c = 1$ and $c = -1$, respectively.
In other words, $\vartheta_3(q)$ is the generating function of the number $r_1(n)$ of ways to write
an integer $n$ as a square of an integer -- 1 for $n = 0$, 2 if $n$ is a non-zero perfect square,
and $0$ otherwise.
Consequently, $\vartheta_3(q)^k$ is the generating function of the number $r_k(n)$ of ways to write
an integer $n$ as a square of $k$ integers. The function $r_k(n)$ is written as
\<^const>‹count_sos› ‹k› ‹n› in Isabelle.
›
definition fps_jacobi_theta_nw :: "'a :: field ⇒ 'a fps" where
"fps_jacobi_theta_nw c = Abs_fps (λn. if n = 0 then 1 else if is_square n then 2 * c ^ n else 0)"
theorem fps_jacobi_theta_power_eq:
"fps_jacobi_theta_nw c ^ k = Abs_fps (λn. of_nat (count_sos k n) * c ^ n)"
proof (induction k)
case (Suc k)
have "fps_jacobi_theta_nw (c::'a) ^ Suc k =
fps_jacobi_theta_nw c * Abs_fps (λn. of_nat (count_sos k n) * c ^ n)"
by (simp add: Suc.IH mult.commute)
also have "… = Abs_fps (λn. of_nat (count_sos (Suc k) n) * c ^ n)" (is "?lhs = ?rhs")
proof (rule fps_ext)
fix n :: nat
have "fps_nth (fps_jacobi_theta_nw (c::'a) * Abs_fps (λn. of_nat (count_sos k n) * c ^ n)) n =
(∑i=0..n. fps_nth (fps_jacobi_theta_nw c) i * of_nat (count_sos k (n - i)) * c ^ (n - i))"
by (simp add: fps_mult_nth sum_distrib_left sum_distrib_right algebra_simps)
also have "… = of_nat (count_sos k n) * c ^ n +
(∑i∈{0<..n}. fps_nth (fps_jacobi_theta_nw c) i *
of_nat (count_sos k (n - i)) * c ^ (n - i))"
(is "_ = _ + ?S")
by (subst sum.head) (auto simp: fps_jacobi_theta_nw_def)
also have "?S = (∑i | i ∈ {0<..n} ∧ is_square i.
2 * of_nat (count_sos k (n - i)) * c ^ n)"
by (rule sum.mono_neutral_cong_right) (auto simp: fps_jacobi_theta_nw_def simp flip: power_add)
also have "… = (∑i ∈ {1..Discrete.sqrt n}.
2 * of_nat (count_sos k (n - i ^ 2)) * c ^ n)"
by (intro sum.reindex_bij_witness[of _ "λi. i ^ 2" Discrete.sqrt])
(auto elim!: is_nth_powerE simp: Discrete.le_sqrt_iff)
also have "of_nat (count_sos k n) * c ^ n + … = of_nat (count_sos (Suc k) n) * c ^ n"
by (simp add: count_sos_Suc sum_distrib_left sum_distrib_right power_add algebra_simps)
finally show "fps_nth ?lhs n = fps_nth ?rhs n"
by simp
qed
finally show ?case .
qed (auto intro!: fps_ext)
corollary fps_jacobi_theta_altdef:
"fps_jacobi_theta_nw c = Abs_fps (λn. of_nat (count_sos 1 n) * c ^ n)"
using fps_jacobi_theta_power_eq[of c 1] by simp
lemma norm_summable_fps_jacobi_theta:
fixes q :: "'a :: {real_normed_field, banach}"
assumes "norm (c * q) < 1"
shows "summable (λn. norm (fps_nth (fps_jacobi_theta_nw c) n * q ^ n))"
proof (rule summable_comparison_test)
show "summable (λn. 2 * norm (c * q) ^ n)"
by (intro summable_mult summable_geometric) (use assms in auto)
show "∃N. ∀n≥N. norm (norm (fps_nth (fps_jacobi_theta_nw c) n * q ^ n)) ≤ 2 * norm (c * q) ^ n"
by (rule exI[of _ 0]) (auto simp: fps_jacobi_theta_nw_def norm_mult norm_power power_mult_distrib)
qed
lemma summable_fps_jacobi_theta:
fixes q :: "'a :: {real_normed_field, banach}"
assumes "norm (c * q) < 1"
shows "summable (λn. fps_nth (fps_jacobi_theta_nw c) n * q ^ n)"
using norm_summable_fps_jacobi_theta[OF assms] by (rule summable_norm_cancel)
lemma summable_ints_symmetric:
fixes f :: "int ⇒ 'a :: {real_normed_vector, banach}"
assumes "summable (λn. norm (f (int n)))"
assumes "⋀n. f (-n) = f n"
shows "f abs_summable_on UNIV" and "summable (λn. norm ((if n = 0 then 1 else 2) *⇩R f (int n)))"
proof -
show "summable (λn. norm ((if n = 0 then 1 else 2) *⇩R f (int n)))"
proof (rule summable_comparison_test)
show "summable (λn. 2 * norm (f n))"
by (intro summable_mult assms)
qed (auto intro!: exI[of _ 0])
next
have "(λn. f (int n)) abs_summable_on UNIV"
using assms by (subst summable_on_UNIV_nonneg_real_iff) auto
also have "?this ⟷ f abs_summable_on {0..}"
by (rule summable_on_reindex_bij_witness[of _ nat int]) auto
finally have 1: "f abs_summable_on {0<..}"
by (rule summable_on_subset) auto
also have "?this ⟷ f abs_summable_on {..<0}"
by (rule summable_on_reindex_bij_witness[of _ uminus uminus]) (use assms(2) in auto)
finally have "f abs_summable_on ({..<0} ∪ {0} ∪ {0<..})"
by (intro summable_on_Un_disjoint 1) auto
also have "({..<(0::int)} ∪ {0} ∪ {0<..}) = UNIV"
by auto
finally show "f abs_summable_on UNIV" .
qed
lemma has_sum_ints_symmetric_iff:
fixes f :: "int ⇒ 'a :: {banach, real_normed_vector}"
assumes "⋀n. f (-n) = f n"
shows "(f has_sum S) UNIV ⟷ ((λn. (if n = 0 then 1 else 2) *⇩R f (int n)) has_sum S) UNIV"
proof
assume *: "((λn. (if n = 0 then 1 else 2) *⇩R f (int n)) has_sum S) UNIV"
have "((λn. (if n = 0 then 1 else 2) *⇩R f (int n)) has_sum (S - f 0)) (UNIV - {0})"
using has_sum_Diff[OF * has_sum_finite[of "{0}"]] by simp
also have "?this ⟷ ((λn. (if n = 0 then 1 else 2) *⇩R f n) has_sum (S - f 0)) {0<..}"
by (intro has_sum_reindex_bij_witness[of _ nat int]) auto
finally have "((λn. (if n = 0 then 1 else 2) *⇩R f n) has_sum S - f 0) {0<..}" .
also have "?this ⟷ ((λn. 2 *⇩R f n) has_sum (S - f 0)) {0<..}"
by (intro has_sum_cong) auto
also have "… ⟷ (f has_sum (S - f 0) /⇩R 2) {0<..}"
by (rule has_sum_scaleR_iff) auto
finally have 1: "(f has_sum (S - f 0) /⇩R 2) {0<..}" .
have "(f has_sum (S - f 0) /⇩R 2) {0<..} ⟷ (f has_sum (S - f 0) /⇩R 2) {..<0}"
by (intro has_sum_reindex_bij_witness[of _ uminus uminus]) (use assms in auto)
with 1 have 2: "(f has_sum (S - f 0) /⇩R 2) {..<0}"
by simp
have "(f has_sum ((S - f 0) /⇩R 2 + (S - f 0) /⇩R 2 + f 0)) ({..<0} ∪ {0<..} ∪ {0})"
by (intro has_sum_Un_disjoint 1 2) (auto simp: has_sum_finite_iff)
also have "{..<0} ∪ {0<..} ∪ {0::int} = UNIV"
by auto
also have "(S - f 0) /⇩R 2 + (S - f 0) /⇩R 2 + f 0 = S"
by (simp flip: mult_2 scaleR_2)
finally show "(f has_sum S) UNIV" .
next
assume *: "(f has_sum S) UNIV"
define S' where "S' = (∑⇩∞n∈{0<..}. f n)"
have "f summable_on {0<..}"
by (rule summable_on_subset_banach[of _ UNIV]) (use * in ‹auto dest: has_sum_imp_summable›)
hence 1: "(f has_sum S') {0<..}"
unfolding S'_def by (rule has_sum_infsum)
have "(f has_sum S') {0<..} ⟷ (f has_sum S') {..<0}"
by (rule has_sum_reindex_bij_witness[of _ uminus uminus]) (use assms in auto)
with 1 have 2: "(f has_sum S') {..<0}"
by simp
have "(f has_sum (S' + S' + f 0)) ({..<0} ∪ {0<..} ∪ {0})"
by (intro has_sum_Un_disjoint 1 2) (auto simp: has_sum_finite_iff)
also have "({..<0} ∪ {0<..} ∪ {0::int}) = UNIV"
by auto
also have "S' + S' + f 0 = 2 *⇩R S' + f 0"
by (simp add: algebra_simps flip: scaleR_2)
finally have 3: "S = 2 *⇩R S' + f 0"
using * has_sum_unique by blast
have "((λn. 2 *⇩R f n) has_sum (2 *⇩R S')) {0<..}"
by (intro has_sum_scaleR 1)
also have "?this ⟷ ((λn. (if n = 0 then 1 else 2) *⇩R f n) has_sum (2 *⇩R S')) {0<..}"
by (intro has_sum_cong) auto
finally have "((λn. (if n = 0 then 1 else 2) *⇩R f n) has_sum (f 0 + 2 *⇩R S')) ({0} ∪ {0<..})"
by (intro has_sum_Un_disjoint) (auto simp: has_sum_finite_iff)
also have "?this ⟷ ((λn. (if n = 0 then 1 else 2) *⇩R f (int n)) has_sum (f 0 + 2 *⇩R S')) UNIV"
by (rule has_sum_reindex_bij_witness[of _ int nat]) auto
finally show "((λn. (if n = 0 then 1 else 2) *⇩R f (int n)) has_sum S) UNIV"
using 3 by (simp add: add.commute)
qed
lemma sums_jacobi_theta_nw_00:
assumes "norm q < 1"
shows "(λn. fps_nth (fps_jacobi_theta_nw 1) n * q ^ n) sums θ⇩3 q"
proof -
define S where "S = (∑n. if is_square n ∧ n > 0 then q ^ n else 0)"
have "((λn. (if n = 0 then 1 else 2) *⇩R q powi (int n ^ 2)) has_sum (θ⇩3 q)) UNIV"
proof (subst has_sum_ints_symmetric_iff [symmetric])
show "((λn. q powi n⇧2) has_sum θ⇩3 q) UNIV"
by (rule has_sum_jacobi_theta_nw_00) fact
qed auto
also have "?this ⟷ ((λn. fps_nth (fps_jacobi_theta_nw 1) n * q ^ n) has_sum
θ⇩3 q) {n. is_square n}"
by (rule has_sum_reindex_bij_witness[of _ Discrete.sqrt "λi. i ^ 2"])
(auto simp: fps_jacobi_theta_nw_def power_int_def scaleR_conv_of_real nat_power_eq
elim!: is_nth_powerE)
also have "… ⟷ ((λn. fps_nth (fps_jacobi_theta_nw 1) n * q ^ n) has_sum
θ⇩3 q) UNIV"
by (intro has_sum_cong_neutral) (auto simp: fps_jacobi_theta_nw_def intro: Nat.gr0I)
finally show ?thesis
by (rule has_sum_imp_sums)
qed
lemma sums_jacobi_theta_nw_01:
assumes "norm q < 1"
shows "(λn. fps_nth (fps_jacobi_theta_nw (-1)) n * q ^ n) sums θ⇩4 q"
proof -
have "(λn. fps_nth (fps_jacobi_theta_nw 1) n * (-q) ^ n) sums θ⇩3 (-q)"
by (rule sums_jacobi_theta_nw_00) (use assms in auto)
also have "(λn. fps_nth (fps_jacobi_theta_nw 1) n * (-q) ^ n) =
(λn. fps_nth (fps_jacobi_theta_nw (-1)) n * q ^ n)"
by (auto simp: fun_eq_iff fps_jacobi_theta_nw_def power_minus')
also have "θ⇩3 (-q) = θ⇩4 q"
by (simp add: jacobi_theta_nw_01_conv_00)
finally show ?thesis .
qed
lemma has_fps_expansion_jacobi_theta_3 [fps_expansion_intros]:
"θ⇩3 has_fps_expansion fps_jacobi_theta_nw 1"
proof (rule has_fps_expansionI)
have "eventually (λq. q ∈ ball 0 1) (nhds (0 :: 'a))"
by (rule eventually_nhds_in_open) auto
thus "eventually (λq. (λn. fps_nth (fps_jacobi_theta_nw 1) n * q ^ n :: 'a) sums θ⇩3 q) (nhds 0)"
by eventually_elim (rule sums_jacobi_theta_nw_00, auto)
qed
lemma has_fps_expansion_jacobi_theta_4 [fps_expansion_intros]:
"θ⇩4 has_fps_expansion fps_jacobi_theta_nw (-1)"
proof (rule has_fps_expansionI)
have "eventually (λq. q ∈ ball 0 1) (nhds (0 :: 'a))"
by (rule eventually_nhds_in_open) auto
thus "eventually (λq. (λn. fps_nth (fps_jacobi_theta_nw (-1)) n * q ^ n :: 'a) sums θ⇩4 q) (nhds 0)"
by eventually_elim (rule sums_jacobi_theta_nw_01, auto)
qed
lemma fps_conv_radius_jacobi_theta_nw [simp]:
fixes c :: "'a :: {banach, real_normed_field}"
shows "fps_conv_radius (fps_jacobi_theta_nw c) = 1 / ereal (norm c)"
proof -
have "fps_conv_radius (fps_jacobi_theta_nw c) =
inverse (limsup (λn. ereal (root n (norm (fps_nth (fps_jacobi_theta_nw c) n)))))"
by (simp add: fps_conv_radius_def conv_radius_def)
also have "limsup (λn. ereal (root n (norm (fps_nth (fps_jacobi_theta_nw c) n)))) = norm c"
(is "?lhs = _")
proof (rule antisym)
have "?lhs ≤ limsup (λn. root n 2 * norm c)"
by (intro Limsup_mono always_eventually)
(auto simp: fps_jacobi_theta_nw_def norm_power real_root_mult real_root_power)
also have "(λn. ereal (root n 2 * norm c)) ⇢ ereal (1 * norm c)"
by (intro tendsto_intros LIMSEQ_root_const) auto
hence "limsup (λn. root n 2 * norm c) = ereal (1 * norm c)"
by (intro lim_imp_Limsup) auto
finally show "?lhs ≤ norm c"
by simp
next
have "limsup ((λn. ereal (root n (norm (fps_nth (fps_jacobi_theta_nw c) n)))) ∘ (λn. n ^ 2)) ≤ ?lhs"
by (rule limsup_subseq_mono) (auto intro!: strict_monoI power_strict_mono)
also have "limsup ((λn. ereal (root n (norm (fps_nth (fps_jacobi_theta_nw c) n)))) ∘ (λn. n ^ 2)) =
limsup ((λn. ereal (root (n^2) 2 * norm c)))"
by (rule Limsup_eq, rule eventually_mono[OF eventually_gt_at_top[of 0]])
(auto simp: o_def fps_jacobi_theta_nw_def norm_power real_root_mult real_root_power)
also have "(λn. ereal (root (n^2) 2 * norm c)) ⇢ ereal (1 * norm c)"
by (intro tendsto_intros filterlim_compose[OF LIMSEQ_root_const]
filterlim_subseq[of "λn. n ^ 2"] strict_monoI power_strict_mono) auto
hence "limsup (λn. ereal (root (n^2) 2 * norm c)) = ereal (1 * norm c)"
by (intro lim_imp_Limsup) auto
finally show "norm c ≤ ?lhs"
by simp
qed
finally show ?thesis
by (simp add: divide_ereal_def)
qed
text ‹
Recall that $\vartheta_2(q) = q^{1/4} \vartheta(q, q)$. Since the factor $q^{1/4}$ has a branch cut,
it is somewhat unpleasant to deal with and we will concentrate only on the factor $\vartheta(q,q)$
for now. This is a holomorphic function on the unit disc except for a removable singularity
at $q = 0$.
For $q\neq 0$ and $|q|<1$, $\vartheta(q,q)$ has following the power series expansion:
\[ \vartheta(q,q) = \sum_{n=-\infty}^{\infty} q^{n(n+1)} = \sum_{n=0}^{\infty} 2 q^{n(n+1)} \]
Note that $n(n+1)$ is twice the triangular number $n(n+1)/2$, so we can also see this as a
series expansion in terms of powers of $q^2$.
›
lemma has_sum_jacobi_theta_nw_10_aux:
assumes q: "norm q < 1" "q ≠ 0"
shows "((λn. 2 * q ^ (n*(n+1))) has_sum jacobi_theta_nome q q) UNIV"
proof -
define S where "S = jacobi_theta_nome q q"
have 1: "((λn. q powi (n*(n+1))) has_sum S) UNIV"
using has_sum_jacobi_theta_nome[of q q]
using q by (simp add: algebra_simps power2_eq_square power_int_add S_def)
have summable: "(λn. q powi (n * (n + 1))) summable_on I" for I
by (rule summable_on_subset_banach, rule has_sum_imp_summable[OF 1]) auto
define S1 where "S1 = (∑⇩∞n∈{0..}. q powi (n*(n+1)))"
have S1: "((λn. q powi (n*(n+1))) has_sum S1) {0..}"
unfolding S1_def by (rule has_sum_infsum[OF summable])
have "((λn. q powi (n*(n+1))) has_sum S1) {0..} ⟷
((λn. q powi (n*(n+1))) has_sum S1) {..<0}"
by (intro has_sum_reindex_bij_witness[of _ "λn. -n-1" "λn. -n-1"])
(auto simp: algebra_simps)
with S1 have S1': "((λn. q powi (n*(n+1))) has_sum S1) {..<0}"
by simp
have "((λn. q powi (n*(n+1))) has_sum (S1 + S1)) ({..<0} ∪ {0..})"
by (intro has_sum_Un_disjoint S1 S1') auto
also have "{..<(0::int)} ∪ {0..} = UNIV"
by auto
finally have 2: "((λn. q powi (n*(n+1))) has_sum (2 * S1)) UNIV"
by simp
from this and 1 have 3: "2 * S1 = S"
using has_sum_unique by blast
have "((λn. q powi (n*(n+1))) has_sum S1) {0..} ⟷ ((λn. q ^ (n*(n+1))) has_sum S1) UNIV"
by (rule has_sum_reindex_bij_witness[of _ int nat])
(auto simp: power_int_def algebra_simps power_add nat_add_distrib nat_mult_distrib)
with S1 show "((λn. 2 * q ^ (n*(n+1))) has_sum S) UNIV"
unfolding 3 [symmetric] by (intro has_sum_cmult_right) auto
qed
lemma sums_jacobi_theta_nw_10_aux:
assumes q: "norm q < 1" "q ≠ 0"
shows "(λn. if ∃i. n = i*(i+1) then 2 * q ^ n else 0) sums jacobi_theta_nome q q"
proof -
have inj: "inj (λi::nat. i * (i + 1))"
by (rule strict_mono_imp_inj_on) (auto simp: strict_mono_Suc_iff)
have "((λn. 2 * q ^ (n*(n+1))) has_sum jacobi_theta_nome q q) UNIV"
by (rule has_sum_jacobi_theta_nw_10_aux) fact+
also have "?this ⟷ ((λn. 2 * q ^ n) has_sum jacobi_theta_nome q q) (range (λi. i*(i+1)))"
by (subst has_sum_reindex[OF inj]) (auto simp: o_def)
also have "… ⟷ ((λn. if ∃i. n = i*(i+1) then 2 * q ^ n else 0) has_sum jacobi_theta_nome q q) UNIV"
by (rule has_sum_cong_neutral) auto
finally show ?thesis
by (rule has_sum_imp_sums)
qed
definition fps_jacobi_theta_nw_10 :: "'a :: field fps" where
"fps_jacobi_theta_nw_10 = Abs_fps (λn. if ∃i. n = i*(i+1) then 2 else 0)"
lemma fps_conv_radius_jacobi_theta_2 [simp]: "fps_conv_radius fps_jacobi_theta_nw_10 = 1"
proof -
have "fps_conv_radius (fps_jacobi_theta_nw_10 :: 'a fps) =
inverse (limsup (λn. ereal (root n (norm (fps_nth fps_jacobi_theta_nw_10 n :: 'a)))))"
unfolding fps_conv_radius_def conv_radius_def ..
also have "limsup (λn. ereal (root n (norm (fps_nth fps_jacobi_theta_nw_10 n :: 'a)))) = 1"
(is "?lhs = _")
proof (rule antisym)
have "?lhs ≤ limsup (λn. root n 2)"
by (intro Limsup_mono always_eventually)
(auto simp: fps_jacobi_theta_nw_10_def norm_power real_root_ge_zero)
also have "(λn. ereal (root n 2)) ⇢ ereal 1"
by (intro tendsto_intros LIMSEQ_root_const) auto
hence "limsup (λn. root n 2) = ereal 1"
by (intro lim_imp_Limsup) auto
finally show "?lhs ≤ 1"
by (simp add: one_ereal_def)
next
define h where "h = (λn::nat. n * (n + 1))"
have h: "strict_mono h"
by (rule strict_monoI_Suc) (auto simp: algebra_simps h_def)
have "limsup ((λn. ereal (root n (norm (fps_nth fps_jacobi_theta_nw_10 n :: 'a)))) ∘ h) ≤ ?lhs"
using h by (rule limsup_subseq_mono)
also have "limsup ((λn. ereal (root n (norm (fps_nth fps_jacobi_theta_nw_10 n :: 'a)))) ∘ h) =
limsup ((λn. ereal (root (h n) 2)))"
by (rule Limsup_eq, rule eventually_mono[OF eventually_gt_at_top[of 0]])
(auto simp: o_def fps_jacobi_theta_nw_10_def h_def algebra_simps)
also have "(λn. ereal (root (h n) 2)) ⇢ ereal 1"
by (intro tendsto_intros filterlim_compose[OF LIMSEQ_root_const]
filterlim_subseq[of h] h) auto
hence "limsup (λn. ereal (root (h n) 2)) = ereal 1"
by (intro lim_imp_Limsup) auto
finally show "1 ≤ ?lhs"
by (simp add: one_ereal_def)
qed
finally show ?thesis
by simp
qed
lemma has_laurent_expansion_jacobi_theta_2 [laurent_expansion_intros]:
"(λq. jacobi_theta_nome q q) has_laurent_expansion fps_to_fls fps_jacobi_theta_nw_10"
unfolding has_laurent_expansion_def
proof safe
show "fls_conv_radius (fps_to_fls fps_jacobi_theta_nw_10 :: complex fls) > 0"
unfolding fls_conv_radius_fps_to_fls by simp
next
have "eventually (λq. q ∈ ball 0 1 - {0}) (at (0 :: complex))"
by (rule eventually_at_in_open) auto
thus "eventually (λq. eval_fls (fps_to_fls fps_jacobi_theta_nw_10) q =
jacobi_theta_nome q q) (at (0::complex))"
proof eventually_elim
case q: (elim q)
have "eval_fls (fps_to_fls fps_jacobi_theta_nw_10) q = eval_fps fps_jacobi_theta_nw_10 q"
by (subst eval_fps_to_fls) (use q in auto)
also have "eval_fps fps_jacobi_theta_nw_10 q = (∑n. fps_nth fps_jacobi_theta_nw_10 n * q ^ n)"
by (simp add: eval_fps_def)
also have "(λn. fps_nth fps_jacobi_theta_nw_10 n * q ^ n) =
(λn. if ∃i. n = i*(i+1) then 2 * q ^ n else 0)"
by (auto simp: fun_eq_iff fps_jacobi_theta_nw_10_def)
also have "(∑n. … n) = jacobi_theta_nome q q"
using sums_jacobi_theta_nw_10_aux[of q] q by (simp add: sums_iff)
finally show ?case .
qed
qed
text ‹
For $\vartheta(q,q)^2$, we can find the following expansion into a double sum:
\[\vartheta(q,q)^2 = \sum_{n=-\infty}^\infty \sum_{n=-\infty}^\infty q^{i(i+1) + j(j+1)}\]
›
lemma has_sum_jacobi_theta_nw_10_aux_square:
fixes q :: complex
assumes q: "norm q < 1" "q ≠ 0"
shows "((λ(i,j). q powi (i*(i+1) + j*(j+1))) has_sum jacobi_theta_nome q q ^ 2) UNIV"
proof -
define S where "S = jacobi_theta_nome q q"
have 1: "((λn. q powi (n*(n+1))) has_sum S) UNIV"
using has_sum_jacobi_theta_nome[of q q]
using q by (simp add: algebra_simps power2_eq_square power_int_add S_def)
have summable: "(λn. q powi (n * (n + 1))) summable_on I" for I
by (rule summable_on_subset_banach, rule has_sum_imp_summable[OF 1]) auto
define S' where "S' = jacobi_theta_nome (norm q) (norm q)"
have 2: "((λn. norm q powi (n*(n+1))) has_sum S') UNIV"
using has_sum_jacobi_theta_nome[of "norm q" "norm q"]
using q by (simp add: algebra_simps power2_eq_square power_int_add S'_def)
have "((λ(i,j). q powi (i*(i+1) + j*(j+1))) has_sum S⇧2) (UNIV × UNIV)"
proof (rule has_sum_SigmaI; (unfold prod.case)?)
show "((λi. S * q powi (i*(i+1))) has_sum S^2) UNIV"
unfolding power2_eq_square by (intro has_sum_cmult_right 1)
next
fix i :: int
show "((λj. q powi (i * (i + 1) + j * (j + 1))) has_sum S * q powi (i * (i + 1))) UNIV"
using has_sum_cmult_left[OF 1, of "q powi (i * (i + 1))"] q
by (simp add: power_int_add mult_ac)
next
have "(λij. norm (case ij of (i,j) ⇒ q powi (i * (i + 1) + j * (j + 1)))) summable_on UNIV × UNIV"
proof (rule summable_on_SigmaI; (unfold prod.case)?)
show "(λj. S' * norm q powi (j * (j + 1))) summable_on UNIV"
using has_sum_imp_summable[OF 2] by (intro summable_on_cmult_right)
next
fix i :: int
show "((λj. norm (q powi (i*(i+1) + j*(j+1)))) has_sum (S' * norm q powi (i*(i+1)))) UNIV"
using has_sum_cmult_left[OF 2, of "norm q powi (i*(i+1))"] q
by (simp add: norm_power_int norm_mult power_int_add mult_ac)
qed auto
thus "(λ(i, j). q powi (i * (i + 1) + j * (j + 1))) summable_on UNIV × UNIV"
by (rule abs_summable_summable)
qed
thus ?thesis
by (simp add: S_def)
qed
text ‹
With some creative reindexing, we find the following power series expansion:
\[ q \vartheta(q^2, q^2)^2 = \sum_{n=0}^\infty r_2(2n+1) q^{2n+1} \]
›
lemma sums_q_times_jacobi_theta_nw_10_aux_square_square:
fixes q :: complex
assumes q: "q ≠ 0" "norm q < 1"
shows "(λn. (if odd n then of_nat (count_sos 2 n) else 0) * q ^ n) sums
(q * jacobi_theta_nome (q⇧2) (q⇧2) ^ 2)"
proof -
define IJ where "IJ = (λn. {(i, j). i⇧2 + j⇧2 = int n})"
have [simp, intro]: "finite (IJ n)" for n
using bij_betw_finite[OF bij_betw_sos_decomps_2[of n]] by (simp add: IJ_def)
have aux: "1 + x ≠ y" if "even x" "even y" for x y :: int
using that by presburger
define S where "S = q * jacobi_theta_nome (q⇧2) (q⇧2) ^ 2"
have "((λ(i,j). (q^2) powi (i*(i+1) + j*(j+1))) has_sum jacobi_theta_nome (q⇧2) (q⇧2) ^ 2) UNIV"
by (intro has_sum_jacobi_theta_nw_10_aux_square)
(use q in ‹auto simp: norm_power power_less_one_iff›)
hence "((λ(i,j). q * (q^2) powi (i*(i+1) + j*(j+1))) has_sum S) (UNIV × UNIV)"
unfolding S_def case_prod_unfold by (intro has_sum_cmult_right) auto
also have "((λ(i,j). q * (q^2) powi (i*(i+1) + j*(j+1)))) =
((λ(i,j). q powi (1 + 2 * (i*(i+1) + j*(j+1)))))" using q
by (auto simp: power_int_add power2_eq_square fun_eq_iff power_int_mult_distrib algebra_simps)
(auto simp flip: power_int_add simp: algebra_simps)?
also have "(… has_sum S) (UNIV × UNIV) ⟷
((λ(i,j). q powi (i ^ 2 + j ^ 2)) has_sum S) {(i,j). odd (i^2+j^2)}"
by (rule has_sum_reindex_bij_witness[of _
"λ(i,j). ((j+i-1) div 2, (j-i-1) div 2)" "λ(i,j). (i-j, i+j+1)"])
(auto elim!: evenE oddE simp: algebra_simps power2_eq_square aux
intro!: arg_cong[of _ _ "λa. q powi a"])
also have "… ⟷ ((λ(n,(i,j)). q powi n) has_sum S) (SIGMA n:{n. odd n}. IJ n)"
proof (rule has_sum_reindex_bij_witness[of _ snd "λ(i,j). (nat (i^2+j^2), (i,j))"])
fix nij assume nij: "nij ∈ Sigma {n. odd n} IJ"
obtain n i j where [simp]: "nij = (n, (i, j))"
using prod_cases3 by blast
from nij have n: "odd n" and ij: "i ^ 2 + j ^ 2 = int n"
by (auto simp: IJ_def)
have "odd (int n)"
using n by simp
also have "int n = i ^ 2 + j ^ 2"
by (rule ij [symmetric])
finally show "snd nij ∈ {(i, j). odd (i⇧2 + j⇧2)}"
by auto
qed (auto simp: IJ_def even_nat_iff)
finally have *: "((λ(n,(i,j)). q powi n) has_sum S) (SIGMA n:{n. odd n}. IJ n)" .
have "((λn. count_sos 2 n * q ^ n) has_sum S) {n. odd n}"
proof (rule has_sum_SigmaD[OF *]; unfold prod.case)
fix n :: nat assume n: "n ∈ {n. odd n}"
have "count_sos 2 n = card (IJ n)"
by (simp add: IJ_def count_sos_2)
thus "((λ(i,j). q powi int n) has_sum complex_of_nat (count_sos 2 n) * q ^ n) (IJ n)"
using q by (simp add: has_sum_finite_iff)
qed
also have "?this ⟷ ((λn. (if odd n then of_nat (count_sos 2 n) else 0) * q ^ n) has_sum S) UNIV"
by (intro has_sum_cong_neutral) auto
finally show "(λn. (λn. if odd n then of_nat (count_sos 2 n) else 0) n * q ^ n) sums S"
by (rule has_sum_imp_sums)
qed
lemma has_laurent_expansion_q_times_jacobi_theta_nw_10_aux_square_square:
defines "F ≡ Abs_fps (λn. if odd n then of_nat (count_sos 2 n) else 0)"
shows "(λq. q * jacobi_theta_nome (q⇧2) (q⇧2) ^ 2) has_laurent_expansion fps_to_fls F"
unfolding has_laurent_expansion_def
proof
have "0 < norm (1/2::complex)"
by simp
also have "fls_conv_radius (fps_to_fls F) ≥ norm (1 / 2 :: complex)"
unfolding fls_conv_radius_fps_to_fls fps_conv_radius_def
by (rule conv_radius_geI) (use sums_q_times_jacobi_theta_nw_10_aux_square_square[of "1/2"]
in ‹auto simp: sums_iff F_def›)
finally show "fls_conv_radius (fps_to_fls F) > 0"
by - (simp_all add: zero_ereal_def)
next
have "eventually (λq. q ∈ ball 0 1 - {0}) (at (0::complex))"
by (rule eventually_at_in_open) auto
thus "∀⇩F q in at 0. eval_fls (fps_to_fls F) q = q * (jacobi_theta_nome (q⇧2) (q⇧2))⇧2"
proof eventually_elim
case q: (elim q)
have "(λn. fps_nth F n * q ^ n) sums (q * (jacobi_theta_nome (q⇧2) (q⇧2))⇧2)"
using sums_q_times_jacobi_theta_nw_10_aux_square_square[of q] q by (simp add: F_def)
thus "eval_fls (fps_to_fls F) q = q * (jacobi_theta_nome (q⇧2) (q⇧2))⇧2"
using eval_fls_eq[of 0 "fps_to_fls F" q "q * (jacobi_theta_nome (q⇧2) (q⇧2))⇧2"]
by (simp add: fls_subdegree_fls_to_fps_gt0)
qed
qed
subsection ‹Identities›
text ‹
Lastly, we derive a variety of identities between the different theta functions.
›
theorem jacobi_theta_nw_00_plus_01_complex: "θ⇩3 q + θ⇩4 q = 2 * θ⇩3 (q ^ 4 :: complex)"
proof (cases "norm q < 1")
case q: True
define f :: "complex ⇒ complex" where "f = (λq. θ⇩3 q + θ⇩4 q - 2 * θ⇩3 (q ^ 4))"
define F :: "complex fps"
where "F = fps_jacobi_theta_nw 1 + fps_jacobi_theta_nw (-1) -
2 * (fps_jacobi_theta_nw 1 oo fps_X ^ 4)"
have [simp]: "is_square (4 :: nat)"
unfolding is_nth_power_def by (rule exI[of _ 2]) auto
have "fps_jacobi_theta_nw 1 + fps_jacobi_theta_nw (-1 :: complex) =
2 * Abs_fps (λn. if n = 0 then 1 else if even n ∧ is_square n then 2 else 0)"
by (intro fps_ext) (auto simp: fps_jacobi_theta_nw_def intro: Nat.gr0I)
also have "Abs_fps (λn. if n = 0 then 1 else if even n ∧ is_square n then 2 else 0) =
fps_compose (fps_jacobi_theta_nw 1) (fps_X ^ 4)"
by (auto simp: fps_eq_iff fps_jacobi_theta_nw_def fps_nth_compose_X_power is_square_mult2_nat_iff
is_nth_power_mult_cancel_left elim!: dvdE)
finally have "F = 0"
by (simp add: F_def)
have "f q = 0"
proof (rule has_fps_expansion_0_analytic_continuation[of f])
have "(λq. θ⇩3 q + θ⇩4 q - 2 * (θ⇩3 ∘ (λq. q ^ 4)) q) has_fps_expansion F"
unfolding F_def by (intro fps_expansion_intros has_fps_expansion_compose) auto
also have "F = 0"
by fact
finally show "f has_fps_expansion 0"
by (simp add: f_def)
next
show "f holomorphic_on ball 0 1"
unfolding f_def by (auto intro!: holomorphic_intros simp: norm_power power_less_one_iff)
qed (use q in auto)
thus ?thesis
by (simp add: f_def)
qed (auto simp: norm_power power_less_one_iff)
lemma jacobi_theta_nw_00_plus_01_real: "θ⇩3 q + θ⇩4 q = 2 * θ⇩3 (q ^ 4 :: real)"
by (subst of_real_eq_iff [where ?'a = complex, symmetric],
unfold of_real_add of_real_mult of_real_diff)
(use jacobi_theta_nw_00_plus_01_complex[of q]
in ‹simp_all flip: jacobi_theta_nome_00_of_real jacobi_theta_nome_01_of_real›)
theorem jacobi_theta_nw_00_plus_01_square_complex:
"θ⇩3 q ^ 2 + θ⇩4 q ^ 2 = 2 * θ⇩3 (q ^ 2 :: complex) ^ 2"
proof (cases "norm q < 1")
case q: True
define F :: "complex fps"
where "F = 2 * fps_compose (fps_jacobi_theta_nw 1 ^ 2) (fps_X ^ 2) -
fps_jacobi_theta_nw 1 ^ 2 - fps_jacobi_theta_nw (-1) ^ 2"
have "(λz. 2 * ((λz. θ⇩3 z ^ 2) ∘ (λz. z ^ 2)) z - θ⇩3 z ^ 2 - θ⇩4 z ^ 2) has_fps_expansion F"
unfolding F_def by (intro fps_expansion_intros has_fps_expansion_compose) auto
also have "F = 0"
proof -
have "2 * fps_compose (Abs_fps (λn. of_nat (count_sos 2 n) :: complex)) (fps_X ^ 2) =
Abs_fps (λn. if even n then of_nat (2 * count_sos 2 n) else 0)"
by (auto elim!: evenE simp: fps_nth_compose_X_power fps_eq_iff count_sos_2_double)
also have "… = fps_jacobi_theta_nw 1 ^ 2 + fps_jacobi_theta_nw (-1) ^ 2"
by (auto simp: fps_eq_iff fps_jacobi_theta_power_eq)
also have "Abs_fps (λn. of_nat (count_sos 2 n)) = fps_jacobi_theta_nw 1 ^ 2"
by (simp add: fps_jacobi_theta_power_eq)
finally show "F = 0"
by (simp add: algebra_simps F_def)
qed
finally have "(λz::complex. 2 * θ⇩3 (z⇧2) ^ 2 - θ⇩3 z ^ 2 - θ⇩4 z ^ 2) has_fps_expansion 0"
by simp
hence "2 * (θ⇩3 (q⇧2))⇧2 - (θ⇩3 q)⇧2 - (θ⇩4 q)⇧2 = 0"
by (rule has_fps_expansion_0_analytic_continuation[where A = "ball 0 1"])
(use q in ‹auto intro!: holomorphic_intros simp: norm_power power_less_one_iff›)
thus ?thesis
by (simp add: algebra_simps)
qed (auto simp: norm_power power_less_one_iff)
corollary midpoint_jacobi_theta_nw_00_01_square_complex:
"midpoint (θ⇩3 q ^ 2) (θ⇩4 q ^ 2) = θ⇩3 (q ^ 2 :: complex) ^ 2"
using jacobi_theta_nw_00_plus_01_square_complex[of q] by (simp add: midpoint_def)
lemma jacobi_theta_nw_00_plus_01_square_real: "θ⇩3 q ^ 2 + θ⇩4 q ^ 2 = 2 * θ⇩3 (q ^ 2 :: real) ^ 2"
by (subst of_real_eq_iff [where ?'a = complex, symmetric],
unfold of_real_add of_real_mult of_real_diff)
(use jacobi_theta_nw_00_plus_01_square_complex[of q]
in ‹simp_all flip: jacobi_theta_nome_00_of_real jacobi_theta_nome_01_of_real›)
theorem jacobi_theta_nw_00_times_01_complex: "θ⇩3 q * θ⇩4 q = (θ⇩4 (q ^ 2) ^ 2 :: complex)"
proof -
have "2 * θ⇩3 q * θ⇩4 q = (θ⇩3 q + θ⇩4 q) ^ 2 - (θ⇩3 q ^ 2 + θ⇩4 q ^ 2)"
by Groebner_Basis.algebra
also have "… = 2 * (2 * θ⇩3 (q ^ 4) ^ 2 - θ⇩3 (q⇧2) ^ 2)"
unfolding jacobi_theta_nw_00_plus_01_complex jacobi_theta_nw_00_plus_01_square_complex
by Groebner_Basis.algebra
also have "2 * θ⇩3 (q ^ 4) ^ 2 - θ⇩3 (q⇧2) ^ 2 = θ⇩4 (q⇧2) ^ 2"
using jacobi_theta_nw_00_plus_01_square_complex[of "q ^ 2"]
by (simp add: algebra_simps)
finally show ?thesis
by simp
qed
lemma jacobi_theta_nw_00_times_01_real: "θ⇩3 q * θ⇩4 q = (θ⇩4 (q ^ 2) ^ 2 :: real)"
by (subst of_real_eq_iff [where ?'a = complex, symmetric],
unfold of_real_add of_real_mult of_real_diff)
(use jacobi_theta_nw_00_times_01_complex[of q]
in ‹simp_all flip: jacobi_theta_nome_00_of_real jacobi_theta_nome_01_of_real›)
lemma jacobi_theta_nw_00_plus_10_square_square_aux:
fixes q :: complex
shows "θ⇩3 q ^ 2 - θ⇩3 (q⇧2) ^ 2 = q * jacobi_theta_nome (q⇧2) (q⇧2) ^ 2"
proof (cases "q ≠ 0 ∧ norm q < 1")
case True
define f :: "complex ⇒ complex"
where "f = (λq. θ⇩3 q ^ 2 - ((λq. θ⇩3 q ^ 2) ∘ (λq. q ^ 2)) q - q * jacobi_theta_nome (q⇧2) (q⇧2) ^ 2)"
define F where "F = (fps_to_fls (fps_jacobi_theta_nw 1))⇧2 -
fps_to_fls ((fps_jacobi_theta_nw 1)⇧2 oo fps_X⇧2) -
fps_to_fls (Abs_fps (λn. if odd n then complex_of_nat (count_sos 2 n) else 0))"
have "f has_laurent_expansion F"
unfolding F_def f_def
by (intro laurent_expansion_intros fps_expansion_intros
has_laurent_expansion_q_times_jacobi_theta_nw_10_aux_square_square
has_laurent_expansion_fps) auto
also have "F = fps_to_fls 0"
unfolding F_def fps_to_fls_power [symmetric] fps_to_fls_minus [symmetric] fps_to_fls_eq_iff
by (auto simp: fps_eq_iff fps_jacobi_theta_power_eq fps_nth_compose_X_power count_sos_2_double
elim!: evenE)
finally have "f has_laurent_expansion 0"
by simp
have "f q = 0"
proof (rule has_laurent_expansion_0_analytic_continuation[of f])
show "f has_laurent_expansion 0"
by fact
show "f holomorphic_on ball 0 1 - {0}"
by (auto simp: f_def o_def norm_power power_less_one_iff intro!: holomorphic_intros)
qed (use True in auto)
thus ?thesis
by (simp add: f_def)
qed (auto simp: norm_power power_less_one_iff)
theorem jacobi_theta_nw_00_plus_10_square_square_complex:
fixes q :: complex
assumes "Re q ≥ 0 ∧ (Re q = 0 ⟶ Im q ≥ 0)"
shows "θ⇩3 (q⇧2) ^ 2 + θ⇩2 (q⇧2) ^ 2 = θ⇩3 q ^ 2"
proof -
have "θ⇩3 q ^ 2 - θ⇩3 (q⇧2) ^ 2 = q * jacobi_theta_nome (q⇧2) (q⇧2) ^ 2"
by (rule jacobi_theta_nw_00_plus_10_square_square_aux)
also have "q = ((q ^ 2) powr (1 / 4)) ^ 2"
proof -
have "((q ^ 2) powr (1 / 4)) ^ 2 = csqrt (q ^ 2)"
using assms by (auto simp add: powr_def csqrt_exp_Ln simp flip: exp_of_nat_mult)
also have "csqrt (q ^ 2) = q"
by (rule csqrt_unique) (use assms in ‹auto simp: not_less›)
finally show ?thesis ..
qed
hence "q * jacobi_theta_nome (q⇧2) (q⇧2) ^ 2 = θ⇩2 (q ^ 2) ^ 2"
by (simp add: jacobi_theta_nome_10_def power_mult_distrib)
finally show ?thesis by (Groebner_Basis.algebra)
qed
lemma jacobi_theta_nw_00_plus_10_square_square_real:
assumes "q ≥ (0::real)"
shows "θ⇩3 (q⇧2) ^ 2 + θ⇩2 (q⇧2) ^ 2 = θ⇩3 q ^ 2"
by (subst of_real_eq_iff [where ?'a = complex, symmetric],
unfold of_real_add of_real_mult of_real_diff)
(use jacobi_theta_nw_00_plus_10_square_square_complex[of q] assms
in ‹simp_all flip: jacobi_theta_nome_00_of_real jacobi_theta_nome_10_complex_of_real›)
theorem jacobi_theta_nw_00_minus_10_square_square_complex:
assumes "0 ≤ Re q ∧ (Re q = 0 ⟶ 0 ≤ Im q)"
shows "θ⇩3 (q⇧2) ^ 2 - θ⇩2 (q⇧2) ^ 2 = θ⇩4 (q :: complex) ^ 2"
using jacobi_theta_nw_00_plus_01_square_complex[of q]
jacobi_theta_nw_00_plus_10_square_square_complex[OF assms]
by Groebner_Basis.algebra
lemma jacobi_theta_nw_00_minus_10_square_square_real:
assumes "q ≥ (0::real)"
shows "θ⇩3 (q⇧2) ^ 2 - θ⇩2 (q⇧2) ^ 2 = θ⇩4 q ^ 2"
using jacobi_theta_nw_00_plus_01_square_real[of q]
jacobi_theta_nw_00_plus_10_square_square_real[OF assms]
by Groebner_Basis.algebra
text ‹
The following shows that the theta nullwerte provide a parameterisation of the
Fermat curve $X^4 + Y^4 = Z^4$:
›
theorem jacobi_theta_nw_pow4_complex: "θ⇩2 q ^ 4 + θ⇩4 q ^ 4 = (θ⇩3 q ^ 4 :: complex)"
proof (cases "norm q < 1")
case q: True
define r where "r = csqrt q"
have q_eq: "q = r ^ 2"
by (simp add: r_def)
have "norm r < 1"
using q by (auto simp: r_def)
have "0 ≤ Re r ∧ (Re r = 0 ⟶ 0 ≤ Im r)"
using csqrt_principal[of q] by (auto simp: r_def simp del: csqrt.sel)
note r = ‹norm r < 1› this
have "θ⇩3 q ^ 4 - θ⇩2 q ^ 4 = (θ⇩3 q ^ 2 + θ⇩2 q ^ 2) * (θ⇩3 q ^ 2 - θ⇩2 q ^ 2)"
by Groebner_Basis.algebra
also have "… = (θ⇩3 r * θ⇩4 r) ^ 2"
using jacobi_theta_nw_00_plus_10_square_square_complex[OF r(2)]
jacobi_theta_nw_00_minus_10_square_square_complex[OF r(2)]
unfolding q_eq by Groebner_Basis.algebra
also have "θ⇩3 r * θ⇩4 r = θ⇩4 q ^ 2"
unfolding q_eq using jacobi_theta_nw_00_times_01_complex[of r] .
finally have "θ⇩3 q ^ 4 - θ⇩2 q ^ 4 = θ⇩4 q ^ 4"
by simp
thus ?thesis
by Groebner_Basis.algebra
qed auto
lemma jacobi_theta_nw_pow4_real: "q ≥ 0 ⟹ θ⇩2 q ^ 4 + θ⇩4 q ^ 4 = (θ⇩3 q ^ 4 :: real)"
by (subst of_real_eq_iff [where ?'a = complex, symmetric],
unfold of_real_add of_real_mult of_real_diff)
(use jacobi_theta_nw_pow4_complex[of q]
in ‹simp_all flip: jacobi_theta_nome_00_of_real jacobi_theta_nome_01_of_real
jacobi_theta_nome_10_complex_of_real›)
subsection ‹Properties of the nullwert functions on the real line›
lemma has_field_derivative_jacobi_theta_nw_00:
fixes q :: "'a :: {real_normed_field,banach}"
assumes q: "norm q < 1"
defines "a ≡ (λn. 2 * (of_nat n + 1)⇧2 * q ^ (n * (n + 2)))"
shows "summable a" "(θ⇩3 has_field_derivative (∑n. a n)) (at q)"
proof -
define F :: "'a fps" where "F = fps_jacobi_theta_nw 1"
define F' where [simp]: "F' = fps_deriv F"
define f' :: "'a ⇒ 'a" where "f' = eval_fps F"
have [simp]: "fps_conv_radius F = 1"
unfolding F_def using fps_conv_radius_jacobi_theta_nw[of "1::'a"]
by (simp add: one_ereal_def)
have "(λn. fps_nth F' n * q ^ n) sums eval_fps F' q"
by (rule sums_eval_fps)
(use q in ‹auto intro!: less_le_trans[OF _ fps_conv_radius_deriv]›)
moreover have "bij_betw (λn. (n+1)^2 - 1) UNIV {n. is_square (Suc n)}"
by (rule bij_betwI[of _ _ _ "λn. Discrete.sqrt (n+1) - 1"]) (auto elim!: is_nth_powerE)
moreover have "strict_mono (λn::nat. (n+1)^2 - 1)"
by (intro strict_monoI_Suc) (auto simp: power2_eq_square)
ultimately have "(λn. fps_nth (fps_deriv F) ((n+1)^2 - 1) * q ^ ((n+1)^2 - 1)) sums
eval_fps (fps_deriv F) q"
by (subst sums_mono_reindex) (auto simp: F_def fps_jacobi_theta_nw_def bij_betw_def)
also have "(λn. fps_nth (fps_deriv F) ((n+1)^2 - 1) * q ^ ((n+1)^2 - 1)) =
(λn. 2 * (of_nat n + 1)^2 * q ^ ((n+1)^2-1))"
by (auto simp: F_def fps_jacobi_theta_nw_def add_ac)
also have "(λn::nat. (n+1) ^ 2 - 1) = (λn. n * (n + 2))"
by (simp add: algebra_simps power2_eq_square)
finally have "a sums eval_fps (fps_deriv F) q"
by (simp only: a_def)
moreover have "(θ⇩3 has_field_derivative (eval_fps F' q)) (at q)"
proof -
have "ereal (norm q) < fps_conv_radius F"
using q by (auto simp: one_ereal_def)
hence "(eval_fps F has_field_derivative (eval_fps F' q)) (at q)"
unfolding F'_def by (rule has_field_derivative_eval_fps)
also have "?this ⟷ ?thesis"
proof (intro DERIV_cong_ev)
have "eventually (λt. t ∈ ball 0 1) (nhds q)"
by (rule eventually_nhds_in_open) (use q in auto)
thus "eventually (λt. eval_fps F t = θ⇩3 t) (nhds q)"
proof eventually_elim
case (elim t)
thus ?case
using sums_jacobi_theta_nw_00[of t] by (simp add: sums_iff eval_fps_def F_def)
qed
qed auto
finally show ?thesis .
qed
ultimately show "summable a" "(θ⇩3 has_field_derivative (∑n. a n)) (at q)"
by (simp_all add: sums_iff)
qed
lemma jacobi_theta_nw_10_le_00:
assumes "q ≥ (0::real)"
shows "θ⇩2 q ≤ θ⇩3 q"
proof (cases "q < 1")
case True
with assms have q: "q ≥ 0" "q < 1"
by auto
define r where "r = sqrt q"
have "0 ≤ θ⇩3 q"
using has_sum_jacobi_theta_nw_00[of q] by (rule has_sum_nonneg) (use q in auto)
have "(θ⇩3 q)⇧2 - (θ⇩2 q)⇧2 = (θ⇩4 r)⇧2"
using jacobi_theta_nw_00_minus_10_square_square_real[of r] q
by (simp add: r_def)
also have "… ≥ 0"
by simp
finally have "(θ⇩3 q)⇧2 ≥ (θ⇩2 q)⇧2"
by simp
thus "θ⇩3 q ≥ θ⇩2 q"
by (rule power2_le_imp_le) (fact ‹θ⇩3 q ≥ 0›)
qed auto
lemma jacobi_theta_nw_00_pos:
fixes q :: real
assumes "q ∈ {-1<..<1}"
shows "θ⇩3 q > 0"
proof -
have pos: "θ⇩3 q > 0" if "q ∈ {0..<1}" for q :: real
using has_sum_0 has_sum_jacobi_theta_nw_00
proof (rule has_sum_strict_mono)
show "0 < q powi 0 ^ 2"
by auto
qed (use that in auto)
have "θ⇩4 q > 0" if q: "q ∈ {0..<1}" for q :: real
proof -
have eq: "θ⇩3 q * θ⇩4 q = (θ⇩4 (q ^ 2) ^ 2)"
by (rule jacobi_theta_nw_00_times_01_real)
have "θ⇩3 q * θ⇩4 q ≥ 0"
by (subst eq) auto
with pos[of q] q have "θ⇩4 q ≥ 0"
by (simp add: zero_le_mult_iff)
have zero_iff: "θ⇩4 q = 0 ⟷ θ⇩4 (q ^ 2) = 0" if "q ∈ {0..<1}" for q :: real
using jacobi_theta_nw_00_times_01_real[of q] pos[of q] that by auto
have "θ⇩4 q ≠ 0"
proof
assume "θ⇩4 q = 0"
have "θ⇩4 (q ^ (2 ^ n)) = 0" for n
proof (induction n)
case (Suc n)
have "θ⇩4 (q ^ (2 ^ Suc n)) = θ⇩4 ((q ^ (2 ^ n)) ^ 2)"
by (simp flip: power_mult add: mult_ac)
also have "… = 0 ⟷ θ⇩4 (q ^ (2 ^ n)) = 0"
by (subst zero_iff [symmetric]) (use q in ‹auto simp: power_less_one_iff›)
finally show ?case
using Suc.IH by simp
qed (use ‹θ⇩4 q = 0› in auto)
hence "(λn. θ⇩4 (q ^ (2 ^ n))) ⇢ 0"
by simp
moreover have "(λn. θ⇩4 (q ^ (2 ^ n))) ⇢ θ⇩4 0"
proof (rule continuous_on_tendsto_compose[of _ θ⇩4])
show "continuous_on {0..<1::real} θ⇩4"
by (intro continuous_intros) auto
show "(λn. q ^ (2 ^ n)) ⇢ 0"
proof (cases "q = 0")
case False
thus ?thesis
using q by real_asymp
qed (auto simp: power_0_left)
qed (use q in ‹auto simp: power_less_one_iff›)
ultimately have "θ⇩4 (0::real) = 0"
using LIMSEQ_unique by blast
thus False
by simp
qed
with ‹θ⇩4 q ≥ 0› show "θ⇩4 q > 0"
by simp
qed
from this[of "-q"] and pos[of q] show ?thesis
using assms by (cases "q ≥ 0") (auto simp: jacobi_theta_nw_01_conv_00)
qed
lemma jacobi_theta_nw_01_pos: "q ∈ {-1<..<1} ⟹ θ⇩4 q > (0::real)"
using jacobi_theta_nw_00_pos[of "-q"]
by (simp add: jacobi_theta_nw_01_conv_00)
lemma jacobi_theta_nw_00_nonneg: "θ⇩3 q ≥ (0::real)"
using jacobi_theta_nw_00_pos[of q] by (cases "norm q < 1") (auto simp: abs_less_iff)
lemma jacobi_theta_nw_01_nonneg: "θ⇩4 q ≥ (0::real)"
by (simp add: jacobi_theta_nw_01_conv_00 jacobi_theta_nw_00_nonneg)
lemma strict_mono_jacobi_theta_nw_00: "strict_mono_on {-1<..<1::real} θ⇩3"
proof -
have theta3_less: "θ⇩3 x < θ⇩3 y" if xy: "0 ≤ x" "x < y" "y < 1" for x y :: real
proof (rule has_sum_strict_mono)
show "((λn. x powi n⇧2) has_sum θ⇩3 x) UNIV" "((λn. y powi n⇧2) has_sum θ⇩3 y) UNIV"
by (rule has_sum_jacobi_theta_nw_00; use xy in simp)+
show "x powi (n^2) ≤ y powi (n^2)" for n :: int
by (intro power_int_mono) (use xy in auto)
show "x powi (1^2) < y powi (1^2)"
using xy by auto
qed auto
have theta4_less: "θ⇩4 x < θ⇩4 y" if xy: "0 ≤ y" "y < x" "x < 1" for x y :: real
proof -
include qpochhammer_inf_notation
have "θ⇩4 x = jacobi_theta_nome (-1) x"
by (simp add: jacobi_theta_nome_01_def)
also have "… = (x⇧2 ; x⇧2)⇩∞ * ((x ; x⇧2)⇩∞) ^ 2"
by (subst jacobi_theta_nome_triple_product_real) (use xy in ‹simp_all add: power2_eq_square›)
also have "… < (x⇧2 ; x⇧2)⇩∞ * ((y ; y⇧2)⇩∞) ^ 2"
proof (intro mult_strict_left_mono power_strict_mono)
show "(x⇧2 ; x⇧2)⇩∞ > 0" "(x ; x⇧2)⇩∞ ≥ 0"
using xy by (auto intro!: qpochhammer_inf_pos qpochhammer_inf_nonneg simp: power_less_one_iff)
next
show "(x ; x⇧2)⇩∞ < (y ; y⇧2)⇩∞"
proof (rule has_prod_less)
show "(λn. 1 - x * (x^2)^n) has_prod (x ; x⇧2)⇩∞"
"(λn. 1 - y * (y^2)^n) has_prod (y ; y⇧2)⇩∞"
by (rule has_prod_qpochhammer_inf; use xy in ‹simp add: power_less_one_iff›)+
next
show "1 - x * (x^2)^0 < 1 - y * (y^2)^0"
using xy by simp
next
fix n :: nat
have "x * (x⇧2)^n = x^(2*n+1)"
by (simp add: power_mult power_add)
also have "… < 1"
by (subst power_less_one_iff) (use xy in auto)
finally show "1 - x * (x⇧2)^n > 0"
by simp
next
fix n :: nat
have "x^(2*n+1) ≥ y^(2*n+1)"
by (intro power_mono) (use xy in auto)
thus "1 - x * (x⇧2) ^ n ≤ 1 - y * (y⇧2) ^ n"
by (simp add: power_mult)
qed
qed auto
also have "… ≤ (y⇧2 ; y⇧2)⇩∞ * ((y ; y⇧2)⇩∞) ^ 2"
proof (intro mult_right_mono zero_le_power)
show "(y ; y⇧2)⇩∞ ≥ 0"
by (intro qpochhammer_inf_nonneg) (use xy in ‹auto simp: power_less_one_iff›)
next
show "(x⇧2 ; x⇧2)⇩∞ ≤ (y⇧2 ; y⇧2)⇩∞"
proof (rule has_prod_le[OF _ _ conjI])
show "(λn. 1 - x⇧2 * (x^2)^n) has_prod (x⇧2 ; x⇧2)⇩∞"
"(λn. 1 - y⇧2 * (y^2)^n) has_prod (y⇧2 ; y⇧2)⇩∞"
by (rule has_prod_qpochhammer_inf; use xy in ‹simp add: power_less_one_iff›)+
next
fix n :: nat
have "x⇧2 * (x⇧2)^n = x^(2*n+2)"
by (simp add: power_mult power_add power2_eq_square)
also have "… ≤ 1"
by (subst power_le_one_iff) (use xy in auto)
finally show "1 - x⇧2 * (x⇧2)^n ≥ 0"
by simp
next
fix n :: nat
have "x^(2*n+2) ≥ y^(2*n+2)"
by (intro power_mono) (use xy in auto)
thus "1 - x⇧2 * (x⇧2) ^ n ≤ 1 - y⇧2 * (y⇧2) ^ n"
by (simp add: power_mult power2_eq_square)
qed
qed
also have "… = jacobi_theta_nome (-1) y"
by (subst jacobi_theta_nome_triple_product_real) (use xy in ‹simp_all add: power2_eq_square›)
also have "… = θ⇩4 y"
by (simp add: jacobi_theta_nome_01_def)
finally show "θ⇩4 x < θ⇩4 y" .
qed
show "strict_mono_on {-1<..<1::real} θ⇩3"
proof (rule strict_mono_onI)
fix x y :: real
assume xy: "x ∈ {-1<..<1}" "y ∈ {-1<..<1}" "x < y"
consider "x ≥ 0" | "y ≤ 0" | "x < 0" "y > 0"
using xy by linarith
thus "θ⇩3 x < θ⇩3 y"
proof cases
assume "x ≥ 0"
thus ?thesis by (intro theta3_less) (use xy in auto)
next
assume "y ≤ 0"
hence "θ⇩4 (-x) < θ⇩4 (-y)"
by (intro theta4_less) (use xy in auto)
thus ?thesis
by (simp add: jacobi_theta_nw_01_conv_00)
next
assume xy': "x < 0" "y > 0"
have "θ⇩4 (-x) < θ⇩4 0"
by (rule theta4_less) (use xy xy' in auto)
moreover have "θ⇩3 0 < θ⇩3 y"
by (rule theta3_less) (use xy xy' in auto)
ultimately show ?thesis
by (simp add: jacobi_theta_nw_01_conv_00)
qed
qed
qed
lemma strict_antimono_jacobi_theta_nw_01: "strict_antimono_on {-1<..<1::real} θ⇩4"
by (auto intro!: monotone_onI strict_mono_onD[OF strict_mono_jacobi_theta_nw_00]
simp: jacobi_theta_nw_01_conv_00)
lemma jacobi_theta_nw_10_nonneg:
assumes "x ≥ 0"
shows "θ⇩2 x ≥ (0::real)"
proof -
consider "x = 0" | "x ≥ 1" | "x ∈ {0<..<1}"
using assms by force
thus ?thesis
proof cases
assume x: "x ∈ {0<..<1}"
show ?thesis
using has_sum_jacobi_theta_nw_10_real
by (rule has_sum_nonneg) (use x in auto)
qed auto
qed
lemma strict_mono_jacobi_theta_nw_10: "strict_mono_on {0::real..<1} θ⇩2"
proof (rule strict_mono_onI)
fix x y :: real
assume xy: "x ∈ {0..<1}" "y ∈ {0..<1}" "x < y"
note mono_rules = strict_mono_jacobi_theta_nw_00 strict_antimono_jacobi_theta_nw_01
have "θ⇩2 x ^ 4 = θ⇩3 x ^ 4 - θ⇩4 x ^ 4"
by (subst jacobi_theta_nw_pow4_real [symmetric]) (use xy in auto)
also have "… < θ⇩3 y ^ 4 - θ⇩4 y ^ 4"
by (intro diff_strict_mono power_strict_mono mono_rules[THEN monotone_onD]
jacobi_theta_nw_00_nonneg jacobi_theta_nw_01_nonneg)
(use xy in auto)
also have "… = θ⇩2 y ^ 4"
by (subst jacobi_theta_nw_pow4_real [symmetric]) (use xy in auto)
finally show "θ⇩2 x < θ⇩2 y"
by (rule power_less_imp_less_base) (use xy in ‹auto intro!: jacobi_theta_nw_10_nonneg›)
qed
lemma jacobi_theta_nw_10_pos:
assumes "x ∈ {0<..<1}"
shows "θ⇩2 x > (0::real)"
using strict_mono_onD[OF strict_mono_jacobi_theta_nw_10, of 0 x] assms by simp
end