Theory Polygonal_Number_Theorem_Legendre
subsection ‹ Legendre's Polygonal Number Theorem ›
text‹We will use the definition of the polygonal numbers from the Gauss Theorem theory file
which also imports the Three Squares Theorem AFP entry \cite{Three_Squares-AFP}.›
theory Polygonal_Number_Theorem_Legendre
imports Polygonal_Number_Theorem_Gauss
begin
text ‹This lemma shows that under certain conditions, an integer $N$ can be written as the sum of four polygonal numbers.›
lemma sum_of_four_polygonal_numbers:
fixes N m :: nat
fixes b :: int
assumes "m ≥ 3"
assumes "N ≥ 2*m"
assumes "[N = b] (mod m)"
assumes odd_b: "odd b"
assumes "b ∈ {1/2 + sqrt (6*N/m - 3) .. 2/3 + sqrt (8*N/m - 8)}"
assumes "N ≥ 9"
shows "∃k1 k2 k3 k4. N = polygonal_number m k1 + polygonal_number m k2 + polygonal_number m k3 + polygonal_number m k4"
proof -
define I where "I = {1/2 + sqrt (6*N/m - 3) .. 2/3 + sqrt (8*N/m - 8)}"
from assms(5) I_def have "b ∈ I" by auto
define a::int where a_def: "a = 2*(N-b) div m + b"
have "m dvd (N-b)" using assms(3)
by (smt (verit, ccfv_threshold) cong_iff_dvd_diff zdvd_zdiffD)
hence "even (2*(N-b) div m)"
by (metis div_mult_swap dvd_triv_left)
hence "odd a" using a_def assms(3) odd_b by auto
from assms(1) have "m^3 ≥ m"
by (simp add: power3_eq_cube)
hence "N ≥ 2 * m" using assms(1,2) by simp
from assms(1) have m_pos: "m > 0" by auto
have "N ≥ b"
proof -
from assms(1) have "m ≥ 1" by auto
hence "1/m ≤ 1" using m_pos by auto
moreover have "N > 0" using ‹N ≥ 2 * m› m_pos by auto
ultimately have "N/m ≤ N"
using divide_less_eq_1 less_eq_real_def by fastforce
hence "sqrt(8*N/m - 8) ≤ sqrt(8*(N-1))" by auto
from assms(1) have "m^3 ≥ 3*3*(3::real)"
by (metis numeral_le_real_of_nat_iff numeral_times_numeral power3_eq_cube power_mono zero_le_numeral)
from ‹N ≥ 9› have "N-1 ≥ 8" by auto
hence "(N-1)^2 ≥ 8*(N-1)" using ‹N > 0› by (simp add: power2_eq_square)
hence "(N-1) ≥ sqrt (8*(N-1))" using ‹N > 0›
by (metis of_nat_0_le_iff of_nat_mono of_nat_power real_sqrt_le_mono real_sqrt_pow2 real_sqrt_power)
hence "N - (1::real) - sqrt(8*N/m - 8) ≥ 0"
using ‹sqrt (real (8 * N) / real m - 8) ≤ sqrt (real (8 * (N - 1)))› ‹9 ≤ N› by linarith
hence expr_pos: "N - (2/3::real) - sqrt(8*N/m - 8) ≥ 0" by auto
have "b ≤ 2/3 + sqrt(8*N/m - 8)" using ‹b ∈ I› I_def by auto
hence "N - b ≥ N - (2/3 + sqrt(8*N/m-8))" by auto
hence "N - b ≥ 0"
using expr_pos of_int_0_le_iff by auto
thus ?thesis by auto
qed
from ‹N ≥ 2 * m› m_pos have "6*N/m - 3 ≥ 0" by (simp add: mult_imp_le_div_pos)
hence "1/2 + sqrt (6*N/m - 3) > 0"
by (smt (verit, del_insts) divide_le_0_1_iff real_sqrt_ge_zero)
with ‹b ∈ I› assms(3) I_def have "b ≥ 1" by auto
hence b_pos: "b ≥ 0" by auto
from ‹b ∈ I› have b_in_I: "(1/2::real) + sqrt (6* real N / real m - 3) ≤ b ∧ b ≤ (2/3::real) + sqrt (8 * real N/real m - 8)" unfolding I_def by auto
from b_pos ‹N ≥ b› a_def have a_pos: "a ≥ 0"
by (smt (verit) m_pos of_nat_0_less_iff pos_imp_zdiv_neg_iff)
hence "a ≥ 1"
by (smt (verit) ‹odd a› dvd_0_right)
have "a - b = 2*(N-b) div m" using a_def by auto
from ‹int m dvd (int N - b)› have "m dvd 2*(N-b)" by fastforce
have "a = 2*(N-b)/m + b" using a_def m_pos
using ‹int m dvd 2 * (int N - b)› by fastforce
hence "a = 2*N/m - 2*b/m + b"
by (simp add: assms diff_divide_distrib of_nat_diff)
hence "(2::real)*N/m = a + 2*b/m - b" by auto
hence "(2::real)*N = (a + 2*b/m - b)*m"
using m_pos by (simp add: divide_eq_eq)
hence "(2::real)*N = m*(a-b) + 2*b"
using ‹int m dvd 2 * (int N - b)› a_def by auto
hence "N = m*(a-b)/2 + b" by auto
hence N_expr: "real N = real m * (of_int a - of_int b) / 2 + of_int b" by auto
have "even (a-b)" using ‹odd a› ‹odd b› by auto
hence "2 dvd m*(a-b)" by auto
hence N_expr2: "N = m*(a-b) div 2 + b" using ‹N = m*(a-b)/2 + b› by linarith
define Nr where "Nr = real_of_nat N"
define mr where "mr = real m"
define ar where "ar = real_of_int a"
define br where "br = real_of_int b"
from assms(1) have "mr ≥ 3" using mr_def by auto
moreover have "Nr ≥ 2*mr" using Nr_def mr_def ‹N ≥ 2 * m› by auto
moreover have "br ≥ 0" using br_def b_pos by auto
moreover have "mr > 0" using mr_def m_pos by auto
moreover have "ar ≥ 0" using ar_def ‹a ≥ 0› by auto
moreover have "Nr = mr*(ar-br)/2 + br" using Nr_def mr_def ar_def br_def N_expr by auto
moreover have "1/2 + sqrt (6*Nr/mr-3) ≤ br ∧ br ≤ 2/3 + sqrt (8*Nr/mr-8)" using Nr_def mr_def br_def b_in_I by auto
ultimately have "br^2 < 4*ar ∧ 3*ar < br^2+2*br+4" using Cauchy_lemma_r_eq_zero
by auto
hence real_ineq:"(real_of_int b)^2 < 4*(real_of_int a) ∧ 3*(real_of_int a) < (real_of_int b)^2 + 2*(real_of_int b) + 4"
using br_def ar_def by auto
hence int_ineq1: "b^2<4*a" using of_int_less_iff by fastforce
from real_ineq have int_ineq2: "3*a < b^2+2*b+4" using of_int_less_iff by fastforce
define an:: nat where "an = nat a"
from a_pos have "an = a" unfolding an_def by auto
define bn:: nat where "bn = nat b"
from b_pos have "bn = b" unfolding bn_def by auto
have "an ≥ 1" using ‹int an = a› ‹a ≥ 1› by auto
moreover have "bn ≥ 1" using ‹int bn = b› ‹b ≥ 1› by auto
moreover have "odd an" using ‹odd a› ‹int an = a› by auto
moreover have "odd bn" using ‹odd b› ‹int bn = b› by auto
moreover have "bn ^ 2 < 4 * an" using int_ineq1 ‹int an = a› ‹int bn = b›
using of_nat_less_iff by fastforce
moreover have "3 * an < bn ^ 2 + 2 * bn + 4" using int_ineq2 ‹int an = a› ‹int bn = b›
using of_nat_less_iff by fastforce
ultimately have "∃s t u v :: int. s ≥ 0 ∧ t ≥ 0 ∧ u ≥ 0 ∧ v ≥ 0 ∧ an = s^2 + t^2 + u^2 + v^2 ∧
bn = s+t+u+v" using four_nonneg_int_sum by auto
hence "∃s t u v :: int. s ≥ 0 ∧ t ≥ 0 ∧ u ≥ 0 ∧ v ≥ 0 ∧ a = s^2 + t^2 + u^2 + v^2 ∧
b = s+t+u+v" using ‹int an = a› ‹int bn = b› by auto
then obtain s t u v :: int where stuv: "s ≥ 0 ∧ t ≥ 0 ∧ u ≥ 0 ∧ v ≥ 0 ∧ a = s^2 + t^2 + u^2 + v^2 ∧
b = s+t+u+v" by auto
hence "N = (m*(s^2+t^2+u^2+v^2-s-t-u-v) div 2) + s+t+u+v" using N_expr2 by (smt (verit, ccfv_threshold))
hence "N = (m*(s^2-s+t^2-t+u^2-u+v^2-v) div 2) + s+t+u+v" by (smt (verit, ccfv_SIG))
hence "N = (m * (s * (s-1) + t * (t-1) + u * (u-1) + v * (v-1)) div 2) +s+t+u+v" by (simp add: power2_eq_square algebra_simps)
hence previous_step: "N = (m * s * (s-1) + m * t * (t-1) + m * u * (u-1) + m * v * (v-1)) div 2 + s+t+u+v" by (simp add: algebra_simps)
moreover have "2 dvd m * s * (s-1)" by simp
moreover have "2 dvd m * t * (t-1)" by simp
moreover have "2 dvd m * u * (u-1)" by simp
moreover have "2 dvd m * v * (v-1)" by simp
ultimately have "N = m * s * (s-1) div 2 + m * t * (t-1) div 2 + m * u * (u-1) div 2 + m * v *(v-1) div 2 + s+t+u+v" by fastforce
hence N_expr3: "N = m * s * (s-1) div 2 + s + m * t * (t-1) div 2 + t + m * u * (u-1) div 2 + u + m * v * (v-1) div 2 + v" by auto
define sn::nat where "sn = nat s"
define tn::nat where "tn = nat t"
define un::nat where "un = nat u"
define vn::nat where "vn = nat v"
have "sn = s" using stuv sn_def by auto
hence "m * sn * (sn-1) = m * s * (s-1)" by fastforce
hence "m * sn * (sn-1) div 2 = m * s * (s-1) div 2" by linarith
have "tn = t" using stuv tn_def by auto
hence "m * tn * (tn-1) = m * t * (t-1)" by fastforce
hence "m * tn * (tn-1) div 2 = m * t * (t-1) div 2" by linarith
have "un = u" using stuv un_def by auto
hence "m * un * (un-1) = m * u * (u-1)" by fastforce
hence "m * un * (un-1) div 2 = m * u * (u-1) div 2" by linarith
have "vn = v" using stuv vn_def by auto
hence "m * vn * (vn-1) = m * v * (v-1)" by fastforce
hence "m * vn * (vn-1) div 2 = m * v * (v-1) div 2" by linarith
have "N = m * sn * (sn-1) div 2 + sn + m * tn * (tn-1) div 2 + tn + m * un * (un-1) div 2 + un + m * vn * (vn-1) div 2 + vn"
using N_expr3 ‹sn = s› ‹tn = t› ‹un = u› ‹vn = v› ‹m * sn * (sn-1) div 2 = m * s * (s-1) div 2› ‹m * tn * (tn-1) div 2 = m * t * (t-1) div 2› ‹m * un * (un-1) div 2 = m * u * (u-1) div 2› ‹m * vn * (vn-1) div 2 = m * v * (v-1) div 2› by linarith
hence "N = polygonal_number m sn + polygonal_number m tn + polygonal_number m un + polygonal_number m vn"
using Polygonal_Number_Theorem_Gauss.polygonal_number_def by presburger
thus ?thesis by blast
qed
text ‹We show Legendre's polygonal number theorem which corresponds to Theorem 1.10 in \cite{nathanson1996}.›
theorem Legendre_Polygonal_Number_Theorem:
fixes m N :: nat
assumes "m ≥ 3"
assumes "N ≥ 28*m^3"
shows "odd m ⟹ ∃k1 k2 k3 k4::nat. N = polygonal_number m k1 + polygonal_number m k2 + polygonal_number m k3 + polygonal_number m k4"
and "even m ⟹ ∃k1 k2 k3 k4 k5::nat. N = polygonal_number m k1 + polygonal_number m k2 + polygonal_number m k3 + polygonal_number m k4 + polygonal_number m k5 ∧ (k1 = 0 ∨ k1 = 1 ∨ k2 = 0 ∨ k2 = 1 ∨ k3 = 0 ∨ k3 = 1 ∨ k4 = 0 ∨ k4 = 1 ∨ k5 = 0 ∨ k5 = 1)"
proof -
define L :: real where "L = (2/3 + sqrt (8*N/m - 8)) - (1/2 + sqrt (6*N/m - 3))"
define I where "I = {1/2 + sqrt (6*N/m - 3) .. 2/3 + sqrt (8*N/m - 8)}"
from assms(1) have "m^3 ≥ m"
by (simp add: power3_eq_cube)
hence "N ≥ 2 * m" using assms by simp
have m_pos: "m > 0" using assms(1) by simp
have "L > 2 * of_nat m" using assms ‹N ≥ 2 * m› m_pos L_def
apply -
apply (rule interval_length_greater_than_2m[where N="of_nat N" and m="of_nat m"])
apply (simp_all)
by (metis (no_types, opaque_lifting) of_nat_le_iff of_nat_mult of_nat_numeral power3_eq_cube)
hence 2: "L > 2 * m" by simp
show thm_odd_m: "odd m ⟹ ∃k1 k2 k3 k4. N = polygonal_number m k1 + polygonal_number m k2 + polygonal_number m k3 + polygonal_number m k4"
proof -
assume odd_m: "odd m"
from assms(1) have "m > 0" by auto
define ce where "ce = ⌈1/2 + sqrt (6*N/m - 3)⌉"
have "∀ i∈{0..2*m-1}. ce + i ≥ ce" by auto
hence lower_bound: "∀ i∈{0..2*m-1}. ce + i ≥ 1/2 + sqrt (6*N/m - 3)" using ceiling_le_iff ce_def by blast
have "2*m-1 + ce ≤ 2/3 + sqrt (8*N/m - 8)" using 2 L_def assms(1) ce_def by linarith
hence upper_bound: "∀ i∈{0..2*m-1}. ce + i ≤ 2/3 + sqrt (8*N/m - 8)" by auto
from lower_bound upper_bound have in_interval: "∀ i∈{0..2*m-1}. ce + i ∈ I" unfolding ce_def I_def by auto
have "∃ f::nat ⇒ int. (∀ i∈{0..m-1}. odd (f i)) ∧ (∀ i∈{1..m-1}. f i = f 0 + 2*i) ∧ (∀ i∈{0..m-1}. f i ∈ I)"
proof -
have ?thesis if odd_f0: "odd ce"
proof -
define g::"nat ⇒ int" where "g i = ce + 2*i"
have "odd (g 0)" using odd_f0 ‹g ≡ λi. ce + int (2 * i)› by auto
hence "∀ i∈{0..m-1}. odd (g i)" using ‹g ≡ λi. ce + int (2 * i)› by auto
have "∀ i∈{1..m-1}. g i = g 0 + 2*i" using ‹g ≡ λi. ce + int (2 * i)› by auto
have "∀ i∈{0..m-1}. 2*i < 2*m-1" using m_pos by auto
hence "∀ i∈{0..m-1}. g i ∈ I" using ‹g ≡ λi. ce + int (2 * i)› in_interval by fastforce
show ?thesis using ‹∀i∈{0..m - 1}. odd (g i)› ‹∀i∈{0..m - 1}. real_of_int (g i) ∈ I› ‹∀i∈{1..m - 1}. g i = g 0 + int(2 * i)› by blast
qed
moreover have ?thesis if "even ce"
proof -
from ‹even ce› have odd_f1: "odd (ce + 1)" by auto
define g::"nat ⇒ int" where "g i = ce + (2*i + 1)"
have "odd (g 0)" using odd_f1 ‹g ≡ λi. ce + int (2 * i + 1)› by auto
hence "∀ i∈{0..m-1}. odd (g i)" using ‹g ≡ λi. ce + int (2 * i + 1)› by auto
have "∀ i∈{1..m-1}. g i = g 0 + 2*i" using ‹g ≡ λi. ce + int (2 * i + 1)› by auto
have "∀ i∈{0..m-1}. 2*i + 1 ≤ 2*m-1" using m_pos by auto
hence "∀ i∈{0..m-1}. g i ∈ I" using ‹g ≡ λi. ce + int (2 * i + 1)› in_interval by fastforce
show ?thesis using ‹∀i∈{0..m - 1}. odd (g i)› ‹∀i∈{0..m - 1}. real_of_int (g i) ∈ I› ‹∀i∈{1..m - 1}. g i = g 0 + int(2 *i)› by blast
qed
ultimately show ?thesis by blast
qed
then obtain f::"nat ⇒ int" where f_def: "(∀ i∈{0..m-1}. odd (f i)) ∧ (∀ i∈{1..m-1}. f i = f 0 + 2*i) ∧ (∀ i∈{0..m-1}. f i ∈ I)" by auto
have inj_lemma: "⟦i ∈ {0..m-1}; j ∈ {0..m-1}; [f i = f j] (mod m)⟧ ⟹ i = j" for i j
proof -
assume asm1: "i ∈ {0..m-1}"
assume asm2: "j ∈ {0..m-1}"
assume asm3: "[f i = f j] (mod m)"
from f_def have "odd (f 0)" by auto
hence "∃ k::int. f 0 = 2*k + 1" by (metis oddE)
then obtain k::int where k_def: "f 0 = 2*k + 1" by auto
have False if case2: "i = 0 ∧ j > 0"
proof -
have "f j = f 0 + 2*j" using f_def case2 asm2 by auto
hence "[2*k + 1 = 2*k + 1 + 2*j] (mod m)" using asm3 case2 k_def by auto
hence "[2*j = 0] (mod m)"
by (metis cong_add_lcancel_0 cong_int_iff cong_sym_eq int_ops(1))
have "coprime 2 m" using odd_m by simp
hence "[j = 0] (mod m)" using ‹[2*j = 0] (mod m)› by (simp add: cong_0_iff coprime_dvd_mult_right_iff)
thus False using asm2 case2 cong_less_modulus_unique_nat by fastforce
qed
moreover have False if case3: "i > 0 ∧ j = 0"
proof -
have "f i = f 0 + 2*i" using f_def case3 asm1 by auto
hence "[2*k + 1 + 2*i = 2*k + 1] (mod m)" using asm3 case3 k_def by auto
hence "[2*i = 0] (mod m)"
by (metis cong_add_lcancel_0 cong_int_iff cong_sym_eq int_ops(1))
have "coprime 2 m" using odd_m by simp
hence "[i = 0] (mod m)" using ‹[2*i = 0] (mod m)› by (simp add: cong_0_iff coprime_dvd_mult_right_iff)
thus False using asm1 case3 cong_less_modulus_unique_nat by fastforce
qed
moreover have ?thesis if case4: "i > 0 ∧ j > 0"
proof -
have "i > 0" and "j > 0" using case4 by auto
have "f i = f 0 + 2*i" using f_def case4 asm1 by auto
moreover have "f j = f 0 + 2*j" using f_def case4 asm2 by auto
ultimately have "[2*k + 1 + 2*i = 2*k + 1 + 2*j] (mod m)" using case4 k_def asm3 by fastforce
hence "[2*i = 2*j] (mod m)"
using cong_add_lcancel cong_int_iff by blast
have "coprime 2 m" using odd_m by simp
hence "[i = j] (mod m)"
using ‹[2 * i = 2 * j] (mod m)› cong_mult_lcancel_nat by auto
thus ?thesis using asm1 asm2 case4 cong_less_modulus_unique_nat by auto
qed
ultimately show ?thesis by fastforce
qed
have complete_cong_class: "∃i ∈ {0..m-1}. [f i = S] (mod m)" for S
proof -
have "(f i) mod m = (f j) mod m ⟹ [f i = f j] (mod m)" for i j
by (simp add: unique_euclidean_semiring_class.cong_def)
hence inj2: "⟦i ∈ {0..m-1}; j ∈ {0..m-1}; (f i) mod m = (f j) mod m⟧ ⟹ i = j" for i j
using inj_lemma by auto
hence injective: "∀i ∈ {0..m-1}. ∀j ∈ {0..m-1}. (f i) mod m = (f j) mod m ⟶ i = j"
by auto
define g :: "nat ⇒ int" where "g i = (f i) mod m"
then have g_inj2: "∀i ∈ {0..m-1}. ∀ j ∈ {0..m-1}. g i = g j ⟶ i = j"
using ‹g ≡ λi. f i mod int m› injective by fastforce
then have g_inj: "inj_on g {0..m-1}"
by (meson inj_onI)
have g_range2: "∀ i ∈ {0..m-1}. g i ∈ {0..m-1}" using ‹g ≡ λi. f i mod int m›
by (metis m_pos Euclidean_Rings.pos_mod_bound Euclidean_Rings.pos_mod_sign atLeastAtMost_iff mod_by_1 mod_if not_gr0 of_nat_0_less_iff of_nat_1 of_nat_diff verit_comp_simplify1(3) zle_diff1_eq)
hence image_subset: "g ` {0..m-1} ⊆ {0..m-1}" by blast
have g_range: "i ∈ {0..m-1} ⟹ g i ∈ {0..m-1}" using ‹g ≡ λi. f i mod int m›
by (metis m_pos Euclidean_Rings.pos_mod_bound Euclidean_Rings.pos_mod_sign atLeastAtMost_iff mod_by_1 mod_if not_gr0 of_nat_0_less_iff of_nat_1 of_nat_diff verit_comp_simplify1(3) zle_diff1_eq)
have card_ge_m: "card (g ` {0..m-1}) ≥ m" using g_inj
by (metis m_pos Suc_diff_1 card_atLeastAtMost card_image minus_nat.diff_0 verit_comp_simplify1(2))
have "card {0..m-1} = m" using m_pos by force
hence card_le_m: "card (g ` {0..m-1}) ≤ m" using m_pos
by (metis card_image g_inj le_refl)
from card_ge_m card_le_m have image_size: "card (g ` {0..m-1}) = m" by auto
with ‹card {0..m-1} = m› have equal_card: "card (g ` {0..m-1}) = card {0..m-1}" by auto
have "finite (g ` {0..m-1})" using image_size by auto
with equal_card image_subset have "g ` {0..m-1} = {0..m-1}"
by (metis card_image card_subset_eq finite_atLeastAtMost_int image_int_atLeastAtMost inj_on_of_nat of_nat_0)
hence "i ∈ {0..m-1} ⟹ ∃ j ∈ {0..m-1}. i = g j" for i by auto
hence "i ∈ {0..m-1} ⟹ ∃ j ∈ {0..m-1}. i = (f j) mod m" for i
using ‹g ≡ λi. f i mod int m› by auto
hence surj: "i ∈ {0..m-1} ⟹ ∃ j ∈ {0..m-1}. [i = f j] (mod m)" for i
by (metis mod_mod_trivial unique_euclidean_semiring_class.cong_def)
have "S mod m ≥ 0" using m_pos by simp
moreover have "S mod m ≤ m-1"
using m_pos by (simp add: of_nat_diff)
ultimately have "S mod m ∈ {0..m-1}" by auto
with surj m_pos have "∃ j ∈ {0..m-1}. [S mod m = f j] (mod m)"
by (metis atLeastAtMost_iff less_eq_nat.simps(1) nonneg_int_cases of_nat_less_iff verit_comp_simplify(3))
thus ?thesis using cong_mod_right cong_sym by blast
qed
have "∃ b::int. [N = b] (mod m) ∧ odd b ∧ b ∈ I"
proof -
have "N mod m ≥ 0" by auto
moreover have "N mod m ≤ m-1"
using m_pos less_Suc_eq_le by fastforce
ultimately have "N mod m ∈ {0..m-1}" by auto
with complete_cong_class have "∃ i. i ∈ {0..m-1} ∧ [f i = N] (mod m)" by blast
then obtain c::nat where c_def: "c ∈ {0..m-1} ∧ [f c = N] (mod m)" by auto
define b::int where "b = f c"
have "[N = b] (mod m)" using b_def c_def by (metis cong_sym)
moreover have "odd b" using b_def f_def c_def by auto
moreover have "b ∈ I" using b_def f_def c_def by auto
ultimately show ?thesis by auto
qed
then obtain b::int where b_def: "[N = b] (mod m) ∧ odd b ∧ b ∈ I" by auto
have "m^3 ≥ m" using m_pos by (auto simp add: power3_eq_cube)
hence "N ≥ 28*m" using assms(1,2) by linarith
hence "N ≥ 2*m" by simp
have "m^3 ≥ 3*3*(3::nat)" using assms(1)
by (metis power3_eq_cube power_mono zero_le_numeral)
hence "N ≥ 28*3*3*(3::nat)" using assms(2) by auto
hence "N ≥ 9" by simp
show ?thesis using sum_of_four_polygonal_numbers assms(1) b_def I_def ‹N ≥ 2 * m› ‹N ≥ 9› by blast
qed
show thm_even_m: "even m ⟹ ∃k1 k2 k3 k4 k5. N = polygonal_number m k1 + polygonal_number m k2 + polygonal_number m k3 + polygonal_number m k4 + polygonal_number m k5 ∧ (k1 = 0 ∨ k1 = 1 ∨ k2 = 0 ∨ k2 = 1 ∨ k3 = 0 ∨ k3 = 1 ∨ k4 = 0 ∨ k4 = 1 ∨ k5 = 0 ∨ k5 = 1)"
proof -
assume even_m: "even m"
from assms(1) have "m > 0" by auto
define ce where "ce = ⌈1/2 + sqrt (6*N/m - 3)⌉"
have "∀ i∈{0..m-1}. ce + i ≥ ce" by auto
hence lower_bound: "∀ i∈{0..m-1}. ce + i ≥ 1/2 + sqrt (6*N/m - 3)" using ceiling_le_iff ce_def by blast
have "m-1 + ce ≤ 2/3 + sqrt (8*N/m - 8)" using 2 L_def assms(1) ce_def by linarith
hence upper_bound: "∀ i∈{0..m-1}. ce + i ≤ 2/3 + sqrt (8*N/m - 8)" by auto
from lower_bound upper_bound have in_interval: "∀ i∈{0..m-1}. ce + i ∈ I" unfolding ce_def I_def by auto
have "∃ f::nat ⇒ int. (∀ i∈{1..m-1}. f i = f 0 + i) ∧ (∀ i∈{0..m-1}. f i ∈ I)"
proof -
define g::"nat ⇒ int" where "g i = ce + i"
have "∀ i∈{1..m-1}. g i = g 0 + i" using ‹g ≡ λi. ce + int i› by auto
have "∀ i∈{0..m-1}. i < m" using m_pos by auto
hence "∀ i∈{0..m-1}. g i ∈ I" using ‹g ≡ λi. ce + int i› in_interval by fastforce
show ?thesis by (metis Num.of_nat_simps(1) ‹∀i∈{0..m - 1}. real_of_int (g i) ∈ I› ‹g ≡ λi. ce + int i› arith_extra_simps(6))
qed
then obtain f::"nat ⇒ int" where f_def: "(∀ i∈{1..m-1}. f i = f 0 + i) ∧ (∀ i∈{0..m-1}. f i ∈ I)" by auto
have inj_lemma: "⟦i ∈ {0..m-1}; j ∈ {0..m-1}; [f i = f j] (mod m)⟧ ⟹ i = j" for i j
proof -
assume asm1: "i ∈ {0..m-1}"
assume asm2: "j ∈ {0..m-1}"
assume asm3: "[f i = f j] (mod m)"
have False if case2: "i = 0 ∧ j > 0"
proof -
have "f j = f 0 + j" using f_def case2 asm2 by auto
hence "[f 0 = f 0 + j] (mod m)" using asm3 case2 by auto
hence "[j = 0] (mod m)"
by (metis cong_add_lcancel_0 cong_int_iff cong_sym_eq int_ops(1))
thus False using asm2 case2 cong_less_modulus_unique_nat by fastforce
qed
moreover have False if case3: "i > 0 ∧ j = 0"
proof -
have "f i = f 0 + i" using f_def case3 asm1 by auto
hence "[f 0 + i = f 0] (mod m)" using asm3 case3 by auto
hence "[i = 0] (mod m)"
by (metis cong_add_lcancel_0 cong_int_iff cong_sym_eq int_ops(1))
thus False using asm1 case3 cong_less_modulus_unique_nat by fastforce
qed
moreover have ?thesis if case4: "i > 0 ∧ j > 0"
proof -
have "i > 0" and "j > 0" using case4 by auto
have "f i = f 0 + i" using f_def case4 asm1 by auto
moreover have "f j = f 0 + j" using f_def case4 asm2 by auto
ultimately have "[f 0 + i = f 0 + j] (mod m)" using case4 asm3 by fastforce
hence "[i = j] (mod m)"
using cong_add_lcancel cong_int_iff by blast
thus ?thesis using asm1 asm2 case4 cong_less_modulus_unique_nat by auto
qed
ultimately show ?thesis by fastforce
qed
have complete_cong_class: "∃i ∈ {0..m-1}. [f i = S] (mod m)" for S
proof -
have "(f i) mod m = (f j) mod m ⟹ [f i = f j] (mod m)" for i j
by (simp add: unique_euclidean_semiring_class.cong_def)
hence inj2: "⟦i ∈ {0..m-1}; j ∈ {0..m-1}; (f i) mod m = (f j) mod m⟧ ⟹ i = j" for i j
using inj_lemma by auto
hence injective: "∀i ∈ {0..m-1}. ∀j ∈ {0..m-1}. (f i) mod m = (f j) mod m ⟶ i = j"
by auto
define g :: "nat ⇒ int" where "g i = (f i) mod m"
then have g_inj2: "∀i ∈ {0..m-1}. ∀ j ∈ {0..m-1}. g i = g j ⟶ i = j"
using ‹g ≡ λi. f i mod int m› injective by fastforce
then have g_inj: "inj_on g {0..m-1}"
by (meson inj_onI)
have g_range2: "∀ i ∈ {0..m-1}. g i ∈ {0..m-1}" using ‹g ≡ λi. f i mod int m›
by (metis m_pos Euclidean_Rings.pos_mod_bound Euclidean_Rings.pos_mod_sign atLeastAtMost_iff mod_by_1 mod_if not_gr0 of_nat_0_less_iff of_nat_1 of_nat_diff verit_comp_simplify1(3) zle_diff1_eq)
hence image_subset: "g ` {0..m-1} ⊆ {0..m-1}" by blast
have g_range: "i ∈ {0..m-1} ⟹ g i ∈ {0..m-1}" using ‹g ≡ λi. f i mod int m›
by (metis m_pos Euclidean_Rings.pos_mod_bound Euclidean_Rings.pos_mod_sign atLeastAtMost_iff mod_by_1 mod_if not_gr0 of_nat_0_less_iff of_nat_1 of_nat_diff verit_comp_simplify1(3) zle_diff1_eq)
have card_ge_m: "card (g ` {0..m-1}) ≥ m" using g_inj
by (metis m_pos Suc_diff_1 card_atLeastAtMost card_image minus_nat.diff_0 verit_comp_simplify1(2))
have "card {0..m-1} = m" using m_pos by force
hence card_le_m: "card (g ` {0..m-1}) ≤ m" using m_pos
by (metis card_image g_inj le_refl)
from card_ge_m card_le_m have image_size: "card (g ` {0..m-1}) = m" by auto
with ‹card {0..m-1} = m› have equal_card: "card (g ` {0..m-1}) = card {0..m-1}" by auto
have "finite (g ` {0..m-1})" using image_size by auto
with equal_card image_subset have "g ` {0..m-1} = {0..m-1}"
by (metis card_image card_subset_eq finite_atLeastAtMost_int image_int_atLeastAtMost inj_on_of_nat of_nat_0)
hence "i ∈ {0..m-1} ⟹ ∃ j ∈ {0..m-1}. i = g j" for i by auto
hence "i ∈ {0..m-1} ⟹ ∃ j ∈ {0..m-1}. i = (f j) mod m" for i
using ‹g ≡ λi. f i mod int m› by auto
hence surj: "i ∈ {0..m-1} ⟹ ∃ j ∈ {0..m-1}. [i = f j] (mod m)" for i
by (metis mod_mod_trivial unique_euclidean_semiring_class.cong_def)
have "S mod m ≥ 0" using m_pos by simp
moreover have "S mod m ≤ m-1"
using m_pos by (simp add: of_nat_diff)
ultimately have "S mod m ∈ {0..m-1}" by auto
with surj m_pos have "∃ j ∈ {0..m-1}. [S mod m = f j] (mod m)"
by (metis atLeastAtMost_iff less_eq_nat.simps(1) nonneg_int_cases of_nat_less_iff verit_comp_simplify(3))
thus ?thesis using cong_mod_right cong_sym by blast
qed
have thm_odd_n: ?thesis if "odd N"
proof -
have "∃ b::int. [N = b] (mod m) ∧ odd b ∧ b ∈ I"
proof -
from complete_cong_class have "∃ i. i ∈ {0..m-1} ∧ [f i = N] (mod m)" by blast
then obtain c::nat where c_def: "c ∈ {0..m-1} ∧ [f c = N] (mod m)" by auto
define b::int where "b = f c"
have "[N = b] (mod m)" using b_def c_def by (metis cong_sym)
moreover have "odd b"
proof
assume "even b"
have "∃k::int. N = b + k*m" using ‹[N = b] (mod m)›
by (metis cong_iff_lin cong_sym_eq mult.commute)
then obtain k::int where k_def: "N = b + k*m" by auto
have "even (k*m)" using even_m by auto
hence "even N" using k_def ‹even b› by presburger
thus False using ‹odd N› by blast
qed
moreover have "b ∈ I" using b_def f_def c_def by auto
ultimately show ?thesis by auto
qed
then obtain b::int where b_def: "[N = b] (mod m) ∧ odd b ∧ b ∈ I" by auto
have "m^3 ≥ m" using m_pos by (auto simp add: power3_eq_cube)
hence "N ≥ 28*m" using assms(1,2) by linarith
hence "N ≥ 2*m" by simp
have "m^3 ≥ 3*3*(3::nat)" using assms(1)
by (metis power3_eq_cube power_mono zero_le_numeral)
hence "N ≥ 28*3*3*(3::nat)" using assms(2) by auto
hence "N ≥ 9" by simp
hence "∃k1 k2 k3 k4. N = polygonal_number m k1 + polygonal_number m k2 + polygonal_number m k3 + polygonal_number m k4"
using sum_of_four_polygonal_numbers assms(1) b_def I_def ‹N ≥ 2 * m› ‹N ≥ 9› by blast
then obtain k1 k2 k3 k4 where "N = polygonal_number m k1 + polygonal_number m k2 + polygonal_number m k3 + polygonal_number m k4" by blast
moreover have "polygonal_number m 0 = 0" using Polygonal_Number_Theorem_Gauss.polygonal_number_def by auto
ultimately have "N = polygonal_number m k1 + polygonal_number m k2 + polygonal_number m k3 + polygonal_number m k4 + polygonal_number m 0" by linarith
thus ?thesis by blast
qed
have thm_even_n: ?thesis if "even N"
proof -
have "∃ b::int. [N-1 = b] (mod m) ∧ odd b ∧ b ∈ I"
proof -
from complete_cong_class have "∃ i. i ∈ {0..m-1} ∧ [f i = N-1] (mod m)" by blast
then obtain c::nat where c_def: "c ∈ {0..m-1} ∧ [f c = N-1] (mod m)" by auto
define b::int where "b = f c"
have "[N-1 = b] (mod m)" using b_def c_def by (metis cong_sym)
moreover have "odd b"
proof
assume "even b"
have "∃k::int. N-1 = b + k*m" using ‹[N-1 = b] (mod m)›
by (metis (full_types) cong_iff_lin cong_sym_eq mult.commute)
then obtain k::int where k_def: "N-1 = b + k*m" by auto
have "even (k*m)" using even_m by auto
hence "even (N-1)" using k_def ‹even b› by presburger
hence "odd N"
by (metis Groups.mult_ac(2) ‹2 * m ≤ N› add_eq_self_zero add_leD1 assms(1) dvd_diffD1 le_trans mult_2_right nat_1_add_1 nat_dvd_1_iff_1 rel_simps(25) zero_neq_numeral)
thus False using ‹even N› by blast
qed
moreover have "b ∈ I" using b_def f_def c_def by auto
ultimately show ?thesis by auto
qed
then obtain b::int where b_def: "[N-1 = b] (mod m) ∧ odd b ∧ b ∈ I" by auto
from b_def have "b ∈ I" by auto
define a::int where a_def: "a = 2*(N-1-b) div m + b"
have "m dvd (N-1-b)" using b_def
by (smt (verit, ccfv_threshold) cong_iff_dvd_diff zdvd_zdiffD)
hence "even (2*(N-1-b) div m)"
by (metis div_mult_swap dvd_triv_left)
hence "odd a" using a_def b_def by auto
from assms(1) have "m^3 ≥ m"
by (simp add: power3_eq_cube)
hence "N ≥ 2 * m" using assms(1,2) by simp
from assms(1) have m_pos: "m > 0" by auto
have "N-1 ≥ b"
proof -
from assms(1) have "m ≥ 1" by auto
hence "1/m ≤ 1" using m_pos by auto
moreover have "N > 0" using ‹N ≥ 2 * m› m_pos by auto
ultimately have "N/m ≤ N"
using divide_less_eq_1 less_eq_real_def by fastforce
hence "sqrt(8*N/m - 8) ≤ sqrt(8*(N-1))" by auto
from assms(1) have "m^3 ≥ 3*3*(3::real)"
by (metis numeral_le_real_of_nat_iff numeral_times_numeral power3_eq_cube power_mono zero_le_numeral)
hence "N ≥ 28*3*3*(3::real)" using assms(2) by linarith
hence "N-6 ≥ 6" by simp
hence "N-6 ≥ 0" by simp
with ‹N-6 ≥ 6› have "(N-6)^2 ≥ 6^2"
using power2_nat_le_eq_le by blast
hence "(N-6)^2 ≥ 24" by simp
hence "(N-2)^2 ≥ 8*(N-1)" by (simp add: power2_eq_square algebra_simps)
hence "(N-2) ≥ sqrt (8*(N-1))" using ‹N > 0›
by (metis of_nat_0_le_iff of_nat_mono of_nat_power real_sqrt_le_mono real_sqrt_pow2 real_sqrt_power)
hence "N - (2::real) - sqrt(8*N/m - 8) ≥ 0"
using ‹sqrt (real (8 * N) / real m - 8) ≤ sqrt (real (8 * (N - 1)))› ‹N-6 ≥ 6› by linarith
hence expr_pos: "N - 1 - (2/3::real) - sqrt(8*N/m - 8) ≥ 0" by auto
have "b ≤ 2/3 + sqrt(8*N/m - 8)" using ‹b ∈ I› I_def by auto
hence "N - 1 - b ≥ N - 1 - (2/3 + sqrt(8*N/m-8))" by auto
hence "N - 1 - b ≥ 0"
using expr_pos of_int_0_le_iff by auto
thus ?thesis by auto
qed
from ‹N ≥ 2 * m› m_pos have "6*N/m - 3 ≥ 0" by (simp add: mult_imp_le_div_pos)
hence "1/2 + sqrt (6*N/m - 3) > 0"
by (smt (verit, del_insts) divide_le_0_1_iff real_sqrt_ge_zero)
with ‹b ∈ I› b_def I_def have "b ≥ 1" by auto
hence b_pos: "b ≥ 0" by auto
from ‹b ∈ I› have b_in_I: "(1/2::real) + sqrt (6* real N / real m - 3) ≤ b ∧ b ≤ (2/3::real) + sqrt (8 * real N/real m - 8)" unfolding I_def by auto
from b_pos ‹N-1 ≥ b› a_def have a_pos: "a ≥ 0"
by (smt (verit) m_pos of_nat_0_less_iff pos_imp_zdiv_neg_iff)
hence "a ≥ 1"
by (smt (verit) ‹odd a› dvd_0_right)
have "a - b = 2*(N-1-b) div m" using a_def by auto
from ‹int m dvd (N - 1 - b)› have "m dvd 2*(N-1-b)" by fastforce
have "a = 2*(N-1-b)/m + b" using a_def m_pos
using ‹int m dvd 2 * (N - 1 - b)› by fastforce
hence "a = 2*(N-1)/m - 2*b/m + b"
by (simp add: assms diff_divide_distrib of_nat_diff)
hence "(2::real)*(N-1)/m = a + 2*b/m - b" by auto
hence "(2::real)*(N-1) = (a + 2*b/m - b)*m"
using m_pos by (simp add: divide_eq_eq)
hence "(2::real)*(N-1) = m*(a-b) + 2*b"
using ‹int m dvd 2 * (N - 1 - b)› a_def by auto
hence "N-1 = m*(a-b)/2 + b" by auto
hence "N = m*(a-b)/2 + b + 1"
using ‹2 * m ≤ N› assms(1) by linarith
hence N_expr: "N = real m * (of_int a - of_int b) / 2 + of_int b + 1" by auto
have "even (a-b)" using ‹odd a› b_def by auto
hence "2 dvd m*(a-b)" by auto
hence N_expr2: "N = m*(a-b) div 2 + b + 1" using ‹N = m*(a-b)/2 + b + 1› by linarith
define Nr where "Nr = real_of_nat N"
define mr where "mr = real m"
define ar where "ar = real_of_int a"
define br where "br = real_of_int b"
from assms(1) have "mr ≥ 3" using mr_def by auto
moreover have "Nr ≥ 2*mr" using Nr_def mr_def ‹N ≥ 2 * m› by auto
moreover have "br ≥ 0" using br_def b_pos by auto
moreover have "mr > 0" using mr_def m_pos by auto
moreover have "ar ≥ 0" using ar_def ‹a ≥ 0› by auto
moreover have "Nr = mr*(ar-br)/2 + br + 1" using Nr_def mr_def ar_def br_def N_expr by auto
moreover have "1/2 + sqrt (6*Nr/mr-3) ≤ br ∧ br ≤ 2/3 + sqrt (8*Nr/mr-8)" using Nr_def mr_def br_def b_in_I by auto
ultimately have "br^2 < 4*ar ∧ 3*ar < br^2+2*br+4" using Cauchy_lemma
by auto
hence real_ineq:"(real_of_int b)^2 < 4*(real_of_int a) ∧ 3*(real_of_int a) < (real_of_int b)^2 + 2*(real_of_int b) + 4"
using br_def ar_def by auto
hence int_ineq1: "b^2<4*a" using of_int_less_iff by fastforce
from real_ineq have int_ineq2: "3*a < b^2+2*b+4" using of_int_less_iff by fastforce
define an:: nat where "an = nat a"
from a_pos have "an = a" unfolding an_def by auto
define bn:: nat where "bn = nat b"
from b_pos have "bn = b" unfolding bn_def by auto
have "an ≥ 1" using ‹int an = a› ‹a ≥ 1› by auto
moreover have "bn ≥ 1" using ‹int bn = b› ‹b ≥ 1› by auto
moreover have "odd an" using ‹odd a› ‹int an = a› by auto
moreover have "odd bn" using b_def ‹int bn = b› by auto
moreover have "bn ^ 2 < 4 * an" using int_ineq1 ‹int an = a› ‹int bn = b›
using of_nat_less_iff by fastforce
moreover have "3 * an < bn ^ 2 + 2 * bn + 4" using int_ineq2 ‹int an = a› ‹int bn = b›
using of_nat_less_iff by fastforce
ultimately have "∃s t u v :: int. s ≥ 0 ∧ t ≥ 0 ∧ u ≥ 0 ∧ v ≥ 0 ∧ an = s^2 + t^2 + u^2 + v^2 ∧
bn = s+t+u+v" using four_nonneg_int_sum by auto
hence "∃s t u v :: int. s ≥ 0 ∧ t ≥ 0 ∧ u ≥ 0 ∧ v ≥ 0 ∧ a = s^2 + t^2 + u^2 + v^2 ∧
b = s+t+u+v" using ‹int an = a› ‹int bn = b› by auto
then obtain s t u v :: int where stuv: "s ≥ 0 ∧ t ≥ 0 ∧ u ≥ 0 ∧ v ≥ 0 ∧ a = s^2 + t^2 + u^2 + v^2 ∧
b = s+t+u+v" by auto
hence "N = (m*(s^2+t^2+u^2+v^2-s-t-u-v) div 2) + s+t+u+v + 1" using N_expr2 by (smt (verit, ccfv_threshold))
hence "N = (m*(s^2-s+t^2-t+u^2-u+v^2-v) div 2) + s+t+u+v + 1" by (smt (verit, ccfv_SIG))
hence "N = (m * (s * (s-1) + t * (t-1) + u * (u-1) + v * (v-1)) div 2) +s+t+u+v + 1" by (simp add: power2_eq_square algebra_simps)
hence previous_step: "N = (m * s * (s-1) + m * t * (t-1) + m * u * (u-1) + m * v * (v-1)) div 2 + s+t+u+v + 1" by (simp add: algebra_simps)
moreover have "2 dvd m * s * (s-1)" by simp
moreover have "2 dvd m * t * (t-1)" by simp
moreover have "2 dvd m * u * (u-1)" by simp
moreover have "2 dvd m * v * (v-1)" by simp
ultimately have "N = m * s * (s-1) div 2 + m * t * (t-1) div 2 + m * u * (u-1) div 2 + m * v *(v-1) div 2 + s+t+u+v + 1" by fastforce
hence N_expr3: "N = m * s * (s-1) div 2 + s + m * t * (t-1) div 2 + t + m * u * (u-1) div 2 + u + m * v * (v-1) div 2 + v + 1" by auto
define sn::nat where "sn = nat s"
define tn::nat where "tn = nat t"
define un::nat where "un = nat u"
define vn::nat where "vn = nat v"
have "sn = s" using stuv sn_def by auto
hence "m * sn * (sn-1) = m * s * (s-1)" by fastforce
hence "m * sn * (sn-1) div 2 = m * s * (s-1) div 2" by linarith
have "tn = t" using stuv tn_def by auto
hence "m * tn * (tn-1) = m * t * (t-1)" by fastforce
hence "m * tn * (tn-1) div 2 = m * t * (t-1) div 2" by linarith
have "un = u" using stuv un_def by auto
hence "m * un * (un-1) = m * u * (u-1)" by fastforce
hence "m * un * (un-1) div 2 = m * u * (u-1) div 2" by linarith
have "vn = v" using stuv vn_def by auto
hence "m * vn * (vn-1) = m * v * (v-1)" by fastforce
hence "m * vn * (vn-1) div 2 = m * v * (v-1) div 2" by linarith
have "N = m * sn * (sn-1) div 2 + sn + m * tn * (tn-1) div 2 + tn + m * un * (un-1) div 2 + un + m * vn * (vn-1) div 2 + vn + 1"
using N_expr3 ‹sn = s› ‹tn = t› ‹un = u› ‹vn = v› ‹m * sn * (sn-1) div 2 = m * s * (s-1) div 2› ‹m * tn * (tn-1) div 2 = m * t * (t-1) div 2› ‹m * un * (un-1) div 2 = m * u * (u-1) div 2› ‹m * vn * (vn-1) div 2 = m * v * (v-1) div 2› by linarith
hence "N = polygonal_number m sn + polygonal_number m tn + polygonal_number m un + polygonal_number m vn + 1"
using Polygonal_Number_Theorem_Gauss.polygonal_number_def by presburger
also have "polygonal_number m 1 = 1" using Polygonal_Number_Theorem_Gauss.polygonal_number_def by auto
ultimately have "N = polygonal_number m sn + polygonal_number m tn + polygonal_number m un + polygonal_number m vn + polygonal_number m 1" by auto
thus ?thesis by blast
qed
show ?thesis using thm_odd_n thm_even_n by blast
qed
qed
end