|
import Mathlib.Algebra.Star.Unitary |
|
import Mathlib.Data.Nat.ModEq |
|
import Mathlib.NumberTheory.Zsqrtd.Basic |
|
import Mathlib.Tactic.Monotonicity |
|
import Mathlib.Algebra.GroupPower.Order |
|
|
|
#align_import number_theory.pell_matiyasevic from "leanprover-community/mathlib"@"795b501869b9fa7aa716d5fdadd00c03f983a605" |
|
|
|
/-! |
|
# Pell's equation and Matiyasevic's theorem |
|
|
|
This file solves Pell's equation, i.e. integer solutions to `x ^ 2 - d * y ^ 2 = 1` |
|
*in the special case that `d = a ^ 2 - 1`*. |
|
This is then applied to prove Matiyasevic's theorem that the power |
|
function is Diophantine, which is the last key ingredient in the solution to Hilbert's tenth |
|
problem. For the definition of Diophantine function, see `NumberTheory.Dioph`. |
|
|
|
For results on Pell's equation for arbitrary (positive, non-square) `d`, see |
|
`NumberTheory.Pell`. |
|
|
|
## Main definition |
|
|
|
* `pell` is a function assigning to a natural number `n` the `n`-th solution to Pell's equation |
|
constructed recursively from the initial solution `(0, 1)`. |
|
|
|
## Main statements |
|
|
|
* `eq_pell` shows that every solution to Pell's equation is recursively obtained using `pell` |
|
* `matiyasevic` shows that a certain system of Diophantine equations has a solution if and only if |
|
the first variable is the `x`-component in a solution to Pell's equation - the key step towards |
|
Hilbert's tenth problem in Davis' version of Matiyasevic's theorem. |
|
* `eq_pow_of_pell` shows that the power function is Diophantine. |
|
|
|
## Implementation notes |
|
|
|
The proof of Matiyasevic's theorem doesn't follow Matiyasevic's original account of using Fibonacci |
|
numbers but instead Davis' variant of using solutions to Pell's equation. |
|
|
|
## References |
|
|
|
* [M. Carneiro, _A Lean formalization of MatiyaseviΔ's theorem_][carneiro2018matiyasevic] |
|
* [M. Davis, _Hilbert's tenth problem is unsolvable_][MR317916] |
|
|
|
## Tags |
|
|
|
Pell's equation, Matiyasevic's theorem, Hilbert's tenth problem |
|
|
|
-/ |
|
|
|
|
|
namespace Pell |
|
|
|
open Nat |
|
|
|
section |
|
|
|
variable {d : β€} |
|
|
|
/-- The property of being a solution to the Pell equation, expressed |
|
as a property of elements of `β€βd`. -/ |
|
def IsPell : β€βd β Prop |
|
| β¨x, yβ© => x * x - d * y * y = 1 |
|
#align pell.is_pell Pell.IsPell |
|
|
|
theorem isPell_norm : β {b : β€βd}, IsPell b β b * star b = 1 |
|
| β¨x, yβ© => by simp [Zsqrtd.ext_iff, IsPell, mul_comm]; ring_nf |
|
#align pell.is_pell_norm Pell.isPell_norm |
|
|
|
theorem isPell_iff_mem_unitary : β {b : β€βd}, IsPell b β b β unitary (β€βd) |
|
| β¨x, yβ© => by rw [unitary.mem_iff, isPell_norm, mul_comm (star _), and_self_iff] |
|
#align pell.is_pell_iff_mem_unitary Pell.isPell_iff_mem_unitary |
|
|
|
theorem isPell_mul {b c : β€βd} (hb : IsPell b) (hc : IsPell c) : IsPell (b * c) := |
|
isPell_norm.2 (by simp [mul_comm, mul_left_comm c, mul_assoc, |
|
star_mul, isPell_norm.1 hb, isPell_norm.1 hc]) |
|
#align pell.is_pell_mul Pell.isPell_mul |
|
|
|
theorem isPell_star : β {b : β€βd}, IsPell b β IsPell (star b) |
|
| β¨x, yβ© => by simp [IsPell, Zsqrtd.star_mk] |
|
#align pell.is_pell_star Pell.isPell_star |
|
|
|
end |
|
|
|
section |
|
|
|
-- Porting note: was parameter in Lean3 |
|
variable {a : β} (a1 : 1 < a) |
|
|
|
private def d (_a1 : 1 < a) := |
|
a * a - 1 |
|
|
|
@[simp] |
|
theorem d_pos : 0 < d a1 := |
|
tsub_pos_of_lt (mul_lt_mul a1 (le_of_lt a1) (by decide) (Nat.zero_le _) : 1 * 1 < a * a) |
|
#align pell.d_pos Pell.d_pos |
|
|
|
-- TODO(lint): Fix double namespace issue |
|
/-- The Pell sequences, i.e. the sequence of integer solutions to `x ^ 2 - d * y ^ 2 = 1`, where |
|
`d = a ^ 2 - 1`, defined together in mutual recursion. -/ |
|
--@[nolint dup_namespace] |
|
def pell : β β β Γ β |
|
-- Porting note: used pattern matching because `Nat.recOn` is noncomputable |
|
| 0 => (1, 0) |
|
| n+1 => ((pell n).1 * a + d a1 * (pell n).2, (pell n).1 + (pell n).2 * a) |
|
#align pell.pell Pell.pell |
|
|
|
/-- The Pell `x` sequence. -/ |
|
def xn (n : β) : β := |
|
(pell a1 n).1 |
|
#align pell.xn Pell.xn |
|
|
|
/-- The Pell `y` sequence. -/ |
|
def yn (n : β) : β := |
|
(pell a1 n).2 |
|
#align pell.yn Pell.yn |
|
|
|
@[simp] |
|
theorem pell_val (n : β) : pell a1 n = (xn a1 n, yn a1 n) := |
|
show pell a1 n = ((pell a1 n).1, (pell a1 n).2) from |
|
match pell a1 n with |
|
| (_, _) => rfl |
|
#align pell.pell_val Pell.pell_val |
|
|
|
@[simp] |
|
theorem xn_zero : xn a1 0 = 1 := |
|
rfl |
|
#align pell.xn_zero Pell.xn_zero |
|
|
|
@[simp] |
|
theorem yn_zero : yn a1 0 = 0 := |
|
rfl |
|
#align pell.yn_zero Pell.yn_zero |
|
|
|
@[simp] |
|
theorem xn_succ (n : β) : xn a1 (n + 1) = xn a1 n * a + d a1 * yn a1 n := |
|
rfl |
|
#align pell.xn_succ Pell.xn_succ |
|
|
|
@[simp] |
|
theorem yn_succ (n : β) : yn a1 (n + 1) = xn a1 n + yn a1 n * a := |
|
rfl |
|
#align pell.yn_succ Pell.yn_succ |
|
|
|
--@[simp] Porting note (#10618): `simp` can prove it |
|
theorem xn_one : xn a1 1 = a := by simp |
|
#align pell.xn_one Pell.xn_one |
|
|
|
--@[simp] Porting note (#10618): `simp` can prove it |
|
theorem yn_one : yn a1 1 = 1 := by simp |
|
#align pell.yn_one Pell.yn_one |
|
|
|
/-- The Pell `x` sequence, considered as an integer sequence.-/ |
|
def xz (n : β) : β€ := |
|
xn a1 n |
|
#align pell.xz Pell.xz |
|
|
|
/-- The Pell `y` sequence, considered as an integer sequence.-/ |
|
def yz (n : β) : β€ := |
|
yn a1 n |
|
#align pell.yz Pell.yz |
|
|
|
section |
|
|
|
/-- The element `a` such that `d = a ^ 2 - 1`, considered as an integer.-/ |
|
def az (a : β) : β€ := |
|
a |
|
#align pell.az Pell.az |
|
|
|
end |
|
|
|
theorem asq_pos : 0 < a * a := |
|
le_trans (le_of_lt a1) |
|
(by have := @Nat.mul_le_mul_left 1 a a (le_of_lt a1); rwa [mul_one] at this) |
|
#align pell.asq_pos Pell.asq_pos |
|
|
|
theorem dz_val : β(d a1) = az a * az a - 1 := |
|
have : 1 β€ a * a := asq_pos a1 |
|
by rw [Pell.d, Int.ofNat_sub this]; rfl |
|
#align pell.dz_val Pell.dz_val |
|
|
|
@[simp] |
|
theorem xz_succ (n : β) : (xz a1 (n + 1)) = xz a1 n * az a + d a1 * yz a1 n := |
|
rfl |
|
#align pell.xz_succ Pell.xz_succ |
|
|
|
@[simp] |
|
theorem yz_succ (n : β) : yz a1 (n + 1) = xz a1 n + yz a1 n * az a := |
|
rfl |
|
#align pell.yz_succ Pell.yz_succ |
|
|
|
/-- The Pell sequence can also be viewed as an element of `β€βd` -/ |
|
def pellZd (n : β) : β€β(d a1) := |
|
β¨xn a1 n, yn a1 nβ© |
|
#align pell.pell_zd Pell.pellZd |
|
|
|
@[simp] |
|
theorem pellZd_re (n : β) : (pellZd a1 n).re = xn a1 n := |
|
rfl |
|
#align pell.pell_zd_re Pell.pellZd_re |
|
|
|
@[simp] |
|
theorem pellZd_im (n : β) : (pellZd a1 n).im = yn a1 n := |
|
rfl |
|
#align pell.pell_zd_im Pell.pellZd_im |
|
|
|
theorem isPell_nat {x y : β} : IsPell (β¨x, yβ© : β€β(d a1)) β x * x - d a1 * y * y = 1 := |
|
β¨fun h => |
|
Nat.cast_inj.1 |
|
(by rw [Int.ofNat_sub (Int.le_of_ofNat_le_ofNat <| Int.le.intro_sub _ h)]; exact h), |
|
fun h => |
|
show ((x * x : β) - (d a1 * y * y : β) : β€) = 1 by |
|
rw [β Int.ofNat_sub <| le_of_lt <| Nat.lt_of_sub_eq_succ h, h]; rflβ© |
|
#align pell.is_pell_nat Pell.isPell_nat |
|
|
|
@[simp] |
|
theorem pellZd_succ (n : β) : pellZd a1 (n + 1) = pellZd a1 n * β¨a, 1β© := by ext <;> simp |
|
#align pell.pell_zd_succ Pell.pellZd_succ |
|
|
|
theorem isPell_one : IsPell (β¨a, 1β© : β€β(d a1)) := |
|
show az a * az a - d a1 * 1 * 1 = 1 by simp [dz_val] |
|
#align pell.is_pell_one Pell.isPell_one |
|
|
|
theorem isPell_pellZd : β n : β, IsPell (pellZd a1 n) |
|
| 0 => rfl |
|
| n + 1 => by |
|
let o := isPell_one a1 |
|
simp; exact Pell.isPell_mul (isPell_pellZd n) o |
|
#align pell.is_pell_pell_zd Pell.isPell_pellZd |
|
|
|
@[simp] |
|
theorem pell_eqz (n : β) : xz a1 n * xz a1 n - d a1 * yz a1 n * yz a1 n = 1 := |
|
isPell_pellZd a1 n |
|
#align pell.pell_eqz Pell.pell_eqz |
|
|
|
@[simp] |
|
theorem pell_eq (n : β) : xn a1 n * xn a1 n - d a1 * yn a1 n * yn a1 n = 1 := |
|
let pn := pell_eqz a1 n |
|
have h : (β(xn a1 n * xn a1 n) : β€) - β(d a1 * yn a1 n * yn a1 n) = 1 := by |
|
repeat' rw [Int.ofNat_mul]; exact pn |
|
have hl : d a1 * yn a1 n * yn a1 n β€ xn a1 n * xn a1 n := |
|
Nat.cast_le.1 <| Int.le.intro _ <| add_eq_of_eq_sub' <| Eq.symm h |
|
Nat.cast_inj.1 (by rw [Int.ofNat_sub hl]; exact h) |
|
#align pell.pell_eq Pell.pell_eq |
|
|
|
instance dnsq : Zsqrtd.Nonsquare (d a1) := |
|
β¨fun n h => |
|
have : n * n + 1 = a * a := by rw [β h]; exact Nat.succ_pred_eq_of_pos (asq_pos a1) |
|
have na : n < a := Nat.mul_self_lt_mul_self_iff.1 (by rw [β this]; exact Nat.lt_succ_self _) |
|
have : (n + 1) * (n + 1) β€ n * n + 1 := by rw [this]; exact Nat.mul_self_le_mul_self na |
|
have : n + n β€ 0 := |
|
@Nat.le_of_add_le_add_right _ (n * n + 1) _ (by ring_nf at this β’; assumption) |
|
Nat.ne_of_gt (d_pos a1) <| by |
|
rwa [Nat.eq_zero_of_le_zero ((Nat.le_add_left _ _).trans this)] at hβ© |
|
#align pell.dnsq Pell.dnsq |
|
|
|
theorem xn_ge_a_pow : β n : β, a ^ n β€ xn a1 n |
|
| 0 => le_refl 1 |
|
| n + 1 => by |
|
simp only [_root_.pow_succ, xn_succ] |
|
exact le_trans (Nat.mul_le_mul_right _ (xn_ge_a_pow n)) (Nat.le_add_right _ _) |
|
#align pell.xn_ge_a_pow Pell.xn_ge_a_pow |
|
|
|
theorem n_lt_a_pow : β n : β, n < a ^ n |
|
| 0 => Nat.le_refl 1 |
|
| n + 1 => by |
|
have IH := n_lt_a_pow n |
|
have : a ^ n + a ^ n β€ a ^ n * a := by |
|
rw [β mul_two] |
|
exact Nat.mul_le_mul_left _ a1 |
|
simp only [_root_.pow_succ, gt_iff_lt] |
|
refine' lt_of_lt_of_le _ this |
|
exact add_lt_add_of_lt_of_le IH (lt_of_le_of_lt (Nat.zero_le _) IH) |
|
#align pell.n_lt_a_pow Pell.n_lt_a_pow |
|
|
|
|