# mathlibdocumentation

number_theory.dioph

# Diophantine functions and Matiyasevic's theorem #

Hilbert's tenth problem asked whether there exists an algorithm which for a given integer polynomial determines whether this polynomial has integer solutions. It was answered in the negative in 1970, the final step being completed by Matiyasevic who showed that the power function is Diophantine.

Here a function is called Diophantine if its graph is Diophantine as a set. A subset S ⊆ ℕ ^ α in turn is called Diophantine if there exists an integer polynomial on α ⊕ β such that v ∈ S iff there exists t : ℕ^β with p (v, t) = 0.

## Main definitions #

• is_poly: a predicate stating that a function is a multivariate integer polynomial.
• poly: the type of multivariate integer polynomial functions.
• dioph: a predicate stating that a set is Diophantine, i.e. a set S ⊆ ℕ^α is Diophantine if there exists a polynomial on α ⊕ β such that v ∈ S iff there exists t : ℕ^β with p (v, t) = 0.
• dioph_fn: a predicate on a function stating that it is Diophantine in the sense that its graph is Diophantine as a set.

## Main statements #

• pell_dioph states that solutions to Pell's equation form a Diophantine set.
• pow_dioph states that the power function is Diophantine, a version of Matiyasevic's theorem.

## Tags #

Matiyasevic's theorem, Hilbert's tenth problem

## TODO #

• Finish the solution of Hilbert's tenth problem.
• Connect poly to mv_polynomial

### Multivariate integer polynomials #

Note that this duplicates mv_polynomial.

inductive is_poly {α : Type u_1} :
((α → )) → Prop
• proj : ∀ {α : Type u_1} (i : α), is_poly (λ (x : α → ), (x i))
• const : ∀ {α : Type u_1} (n : ), is_poly (λ (x : α → ), n)
• sub : ∀ {α : Type u_1} {f g : (α → )}, is_poly (λ (x : α → ), f x - g x)
• mul : ∀ {α : Type u_1} {f g : (α → )}, is_poly (λ (x : α → ), f x * g x)

A predicate asserting that a function is a multivariate integer polynomial. (We are being a bit lazy here by allowing many representations for multiplication, rather than only allowing monomials and addition, but the definition is equivalent and this is easier to use.)

theorem is_poly.neg {α : Type u_1} {f : (α → )} :
is_poly (-f)
theorem is_poly.add {α : Type u_1} {f g : (α → )} (hf : is_poly f) (hg : is_poly g) :
is_poly (f + g)
def poly (α : Type u) :
Type u

The type of multivariate integer polynomials

Equations
Instances for poly
@[protected, instance]
def poly.fun_like {α : Type u_1} :
fun_like (poly α) (α → ) (λ (_x : α → ), )
Equations
@[protected, instance]
def poly.has_coe_to_fun {α : Type u_1} :
(λ (_x : poly α), (α → ))

Helper instance for when there are too many metavariables to apply fun_like.has_coe_to_fun directly.

Equations
@[protected]
theorem poly.is_poly {α : Type u_1} (f : poly α) :

The underlying function of a poly is a polynomial

@[ext]
theorem poly.ext {α : Type u_1} {f g : poly α} :
(∀ (x : α → ), f x = g x)f = g

Extensionality for poly α

def poly.proj {α : Type u_1} (i : α) :
poly α

The ith projection function, x_i.

Equations
@[simp]
theorem poly.proj_apply {α : Type u_1} (i : α) (x : α → ) :
(poly.proj i) x = (x i)
def poly.const {α : Type u_1} (n : ) :
poly α

The constant function with value n : ℤ.

Equations
• = λ (x : α → ), n, _⟩
@[simp]
theorem poly.const_apply {α : Type u_1} (n : ) (x : α → ) :
@[protected, instance]
def poly.has_zero {α : Type u_1} :
Equations
@[protected, instance]
def poly.has_one {α : Type u_1} :
Equations
@[protected, instance]
def poly.has_neg {α : Type u_1} :
Equations
@[protected, instance]
def poly.has_add {α : Type u_1} :
Equations
@[protected, instance]
def poly.has_sub {α : Type u_1} :
Equations
@[protected, instance]
def poly.has_mul {α : Type u_1} :
Equations
@[simp]
theorem poly.coe_zero {α : Type u_1} :
@[simp]
theorem poly.coe_one {α : Type u_1} :
@[simp]
theorem poly.coe_neg {α : Type u_1} (f : poly α) :
@[simp]
theorem poly.coe_add {α : Type u_1} (f g : poly α) :
(f + g) = f + g
@[simp]
theorem poly.coe_sub {α : Type u_1} (f g : poly α) :
(f - g) = f - g
@[simp]
theorem poly.coe_mul {α : Type u_1} (f g : poly α) :
(f * g) = f * g
@[simp]
theorem poly.zero_apply {α : Type u_1} (x : α → ) :
0 x = 0
@[simp]
theorem poly.one_apply {α : Type u_1} (x : α → ) :
1 x = 1
@[simp]
theorem poly.neg_apply {α : Type u_1} (f : poly α) (x : α → ) :
(-f) x = -f x
@[simp]
theorem poly.add_apply {α : Type u_1} (f g : poly α) (x : α → ) :
(f + g) x = f x + g x
@[simp]
theorem poly.sub_apply {α : Type u_1} (f g : poly α) (x : α → ) :
(f - g) x = f x - g x
@[simp]
theorem poly.mul_apply {α : Type u_1} (f g : poly α) (x : α → ) :
(f * g) x = f x * g x
@[protected, instance]
def poly.inhabited (α : Type u_1) :
Equations
@[protected, instance]
def poly.add_comm_group {α : Type u_1} :
Equations
@[protected, instance]
def poly.add_group_with_one {α : Type u_1} :
Equations
@[protected, instance]
def poly.comm_ring {α : Type u_1} :
Equations
theorem poly.induction {α : Type u_1} {C : poly α → Prop} (H1 : ∀ (i : α), C (poly.proj i)) (H2 : ∀ (n : ), C (poly.const n)) (H3 : ∀ (f g : poly α), C fC gC (f - g)) (H4 : ∀ (f g : poly α), C fC gC (f * g)) (f : poly α) :
C f
def poly.sumsq {α : Type u_1} :
list (poly α)poly α

The sum of squares of a list of polynomials. This is relevant for Diophantine equations, because it means that a list of equations can be encoded as a single equation: x = 0 ∧ y = 0 ∧ z = 0 is equivalent to x^2 + y^2 + z^2 = 0.

Equations
theorem poly.sumsq_nonneg {α : Type u_1} (x : α → ) (l : list (poly α)) :
theorem poly.sumsq_eq_zero {α : Type u_1} (x : α → ) (l : list (poly α)) :
(poly.sumsq l) x = 0 list.all₂ (λ (a : poly α), a x = 0) l
def poly.map {α : Type u_1} {β : Type u_2} (f : α → β) (g : poly α) :
poly β

Map the index set of variables, replacing x_i with x_(f i).

Equations
@[simp]
theorem poly.map_apply {α : Type u_1} {β : Type u_2} (f : α → β) (g : poly α) (v : β → ) :
(poly.map f g) v = g (v f)

### Diophantine sets #

def dioph {α : Type u} (S : set (α → )) :
Prop

A set S ⊆ ℕ^α is Diophantine if there exists a polynomial on α ⊕ β such that v ∈ S iff there exists t : ℕ^β with p (v, t) = 0.

Equations
theorem dioph.ext {α : Type u} {S S' : set (α → )} (d : dioph S) (H : ∀ (v : α → ), v S v S') :
theorem dioph.of_no_dummies {α : Type u} (S : set (α → )) (p : poly α) (h : ∀ (v : α → ), S v p v = 0) :
theorem dioph.inject_dummies_lem {α β γ : Type u} (f : β → γ) (g : γ → ) (inv : ∀ (x : β), g (f x) = ) (p : poly β)) (v : α → ) :
(∃ (t : β → ), p (sum.elim v t) = 0) ∃ (t : γ → ), (poly.map (sum.inr f)) p) (sum.elim v t) = 0
theorem dioph.inject_dummies {α β γ : Type u} {S : set (α → )} (f : β → γ) (g : γ → ) (inv : ∀ (x : β), g (f x) = ) (p : poly β)) (h : ∀ (v : α → ), S v ∃ (t : β → ), p (sum.elim v t) = 0) :
∃ (q : poly γ)), ∀ (v : α → ), S v ∃ (t : γ → ), q (sum.elim v t) = 0
theorem dioph.reindex_dioph {α : Type u} (β : Type u) {S : set (α → )} (f : α → β) (d : dioph S) :
dioph {v : β → | v f S}
theorem dioph.dioph_list.all₂ {α : Type u} (l : list (set (α → ))) (d : l) :
dioph {v : α → | list.all₂ (λ (S : set (α → )), v S) l}
theorem dioph.inter {α : Type u} {S S' : set (α → )} (d : dioph S) (d' : dioph S') :
dioph (S S')
theorem dioph.union {α : Type u} {S S' : set (α → )} (d : dioph S) (d' : dioph S') :
dioph (S S')
def dioph.dioph_pfun {α : Type u} (f : (α → ) →. ) :
Prop

A partial function is Diophantine if its graph is Diophantine.

Equations
def dioph.dioph_fn {α : Type u} (f : (α → )) :
Prop

A function is Diophantine if its graph is Diophantine.

Equations
theorem dioph.reindex_dioph_fn {α β : Type u} {f : (α → )} (g : α → β) (d : dioph.dioph_fn f) :
dioph.dioph_fn (λ (v : β → ), f (v g))
theorem dioph.ex_dioph {α β : Type u} {S : set β)} :
dioph {v : α → | ∃ (x : β → ), x S}
theorem dioph.ex1_dioph {α : Type u} {S : set (option α)} :
dioph {v : α → | ∃ (x : ), v S}
theorem dioph.dom_dioph {α : Type u} {f : (α → ) →. } (d : dioph.dioph_pfun f) :
theorem dioph.dioph_fn_iff_pfun {α : Type u} (f : (α → )) :
theorem dioph.abs_poly_dioph {α : Type u} (p : poly α) :
dioph.dioph_fn (λ (v : α → ), (p v).nat_abs)
theorem dioph.proj_dioph {α : Type u} (i : α) :
dioph.dioph_fn (λ (v : α → ), v i)
theorem dioph.dioph_pfun_comp1 {α : Type u} {S : set (option α)} (d : dioph S) {f : (α → ) →. } (df : dioph.dioph_pfun f) :
dioph {v : α → | ∃ (h : f.dom v), option.elim (f.fn v h) v S}
theorem dioph.dioph_fn_comp1 {α : Type u} {S : set (option α)} (d : dioph S) {f : (α → )} (df : dioph.dioph_fn f) :
dioph {v : α → | option.elim (f v) v S}
theorem dioph.dioph_fn_vec_comp1 {n : } {S : set n.succ)} (d : dioph S) {f : n} (df : dioph.dioph_fn f) :
dioph {v : n | f v::v S}
theorem dioph.vec_ex1_dioph (n : ) {S : set n.succ)} (d : dioph S) :
dioph {v : fin2 n | ∃ (x : ), x::v S}
theorem dioph.dioph_fn_vec {n : } (f : n) :
dioph {v : fin2 n.succ | f (v fin2.fs) = v fin2.fz}
theorem dioph.dioph_pfun_vec {n : } (f : n →. ) :
dioph {v : fin2 n.succ | f.graph (v fin2.fs, v fin2.fz)}
theorem dioph.dioph_fn_compn {α : Type} {n : } {S : set fin2 n)} (d : dioph S) {f : vector3 ((α → )) n} (df : f) :
dioph {v : α → | (λ (i : fin2 n), f i v) S}
theorem dioph.dioph_comp {α : Type} {n : } {S : set n)} (d : dioph S) (f : vector3 ((α → )) n) (df : f) :
dioph {v : α → | (λ (i : fin2 n), f i v) S}
theorem dioph.dioph_fn_comp {α : Type} {n : } {f : n} (df : dioph.dioph_fn f) (g : vector3 ((α → )) n) (dg : g) :
dioph.dioph_fn (λ (v : α → ), f (λ (i : fin2 n), g i v))
theorem dioph.proj_dioph_of_nat {n : } (m : ) [ n] :
dioph.dioph_fn (λ (v : n), v (fin2.of_nat' m))
theorem dioph.const_dioph {α : Type} (n : ) :
theorem dioph.dioph_comp2 {α : Type} {f g : (α → )} (df : dioph.dioph_fn f) (dg : dioph.dioph_fn g) {S : → Prop} (d : dioph (λ (v : 2), S (v (fin2.of_nat' 0)) (v (fin2.of_nat' 1)))) :
dioph (λ (v : α → ), S (f v) (g v))
theorem dioph.dioph_fn_comp2 {α : Type} {f g : (α → )} (df : dioph.dioph_fn f) (dg : dioph.dioph_fn g) {h : } (d : dioph.dioph_fn (λ (v : 2), h (v (fin2.of_nat' 0)) (v (fin2.of_nat' 1)))) :
dioph.dioph_fn (λ (v : α → ), h (f v) (g v))
theorem dioph.eq_dioph {α : Type} {f g : (α → )} (df : dioph.dioph_fn f) (dg : dioph.dioph_fn g) :
dioph (λ (v : α → ), f v = g v)
theorem dioph.add_dioph {α : Type} {f g : (α → )} (df : dioph.dioph_fn f) (dg : dioph.dioph_fn g) :
dioph.dioph_fn (λ (v : α → ), f v + g v)
theorem dioph.mul_dioph {α : Type} {f g : (α → )} (df : dioph.dioph_fn f) (dg : dioph.dioph_fn g) :
dioph.dioph_fn (λ (v : α → ), f v * g v)
theorem dioph.le_dioph {α : Type} {f g : (α → )} (df : dioph.dioph_fn f) (dg : dioph.dioph_fn g) :
dioph {v : α → | f v g v}
theorem dioph.lt_dioph {α : Type} {f g : (α → )} (df : dioph.dioph_fn f) (dg : dioph.dioph_fn g) :
dioph {v : α → | f v < g v}
theorem dioph.ne_dioph {α : Type} {f g : (α → )} (df : dioph.dioph_fn f) (dg : dioph.dioph_fn g) :
dioph {v : α → | f v g v}
theorem dioph.sub_dioph {α : Type} {f g : (α → )} (df : dioph.dioph_fn f) (dg : dioph.dioph_fn g) :
dioph.dioph_fn (λ (v : α → ), f v - g v)
theorem dioph.dvd_dioph {α : Type} {f g : (α → )} (df : dioph.dioph_fn f) (dg : dioph.dioph_fn g) :
dioph (λ (v : α → ), f v g v)
theorem dioph.mod_dioph {α : Type} {f g : (α → )} (df : dioph.dioph_fn f) (dg : dioph.dioph_fn g) :
dioph.dioph_fn (λ (v : α → ), f v % g v)
theorem dioph.modeq_dioph {α : Type} {f g : (α → )} (df : dioph.dioph_fn f) (dg : dioph.dioph_fn g) {h : (α → )} (dh : dioph.dioph_fn h) :
dioph (λ (v : α → ), f v g v [MOD h v])
theorem dioph.div_dioph {α : Type} {f g : (α → )} (df : dioph.dioph_fn f) (dg : dioph.dioph_fn g) :
dioph.dioph_fn (λ (v : α → ), f v / g v)
theorem dioph.pell_dioph  :
dioph (λ (v : 4), ∃ (h : 1 < v (fin2.of_nat' 0)), (v (fin2.of_nat' 1)) = v (fin2.of_nat' 2) (v (fin2.of_nat' 1)) = v (fin2.of_nat' 3))
theorem dioph.xn_dioph  :
dioph.dioph_pfun (λ (v : 2), {dom := 1 < v (fin2.of_nat' 0), get := λ (h : 1 < v (fin2.of_nat' 0)), (v (fin2.of_nat' 1))})
theorem dioph.pow_dioph {α : Type} {f g : (α → )} (df : dioph.dioph_fn f) (dg : dioph.dioph_fn g) :
dioph.dioph_fn (λ (v : α → ), f v ^ g v)

A version of Matiyasevic's theorem