mathlib documentation

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 #

Main statements #

References #

Tags #

Matiyasevic's theorem, Hilbert's tenth problem

TODO #

Multivariate integer polynomials #

Note that this duplicates mv_polynomial.

inductive is_poly {α : Type u_1} :
((α → )) → Prop

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 fis_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} :
has_coe_to_fun (poly α) (λ (_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
@[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
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 : γ → option β) (inv : ∀ (x : β), g (f x) = option.some x) (p : poly β)) (v : α → ) :
(∃ (t : β → ), p (sum.elim v t) = 0) ∃ (t : γ → ), (poly.map (sum.elim sum.inl (sum.inr f)) p) (sum.elim v t) = 0
theorem dioph.inject_dummies {α β γ : Type u} {S : set (α → )} (f : β → γ) (g : γ → option β) (inv : ∀ (x : β), g (f x) = option.some 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 : list.all₂ dioph 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 Sdioph {v : α → | ∃ (x : β → ), sum.elim v x S}
theorem dioph.ex1_dioph {α : Type u} {S : set (option α)} :
dioph Sdioph {v : α → | ∃ (x : ), option.cons 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.cons (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.cons (f v) v S}
theorem dioph.dioph_fn_vec_comp1 {n : } {S : set (vector3 n.succ)} (d : dioph S) {f : vector3 n} (df : dioph.dioph_fn f) :
dioph {v : vector3 n | f v::v S}
theorem dioph.vec_ex1_dioph (n : ) {S : set (vector3 n.succ)} (d : dioph S) :
dioph {v : fin2 n | ∃ (x : ), x::v S}
theorem dioph.dioph_fn_vec {n : } (f : vector3 n) :
theorem dioph.dioph_fn_compn {α : Type} {n : } {S : set fin2 n)} (d : dioph S) {f : vector3 ((α → )) n} (df : vector_allp dioph.dioph_fn f) :
dioph {v : α → | sum.elim v (λ (i : fin2 n), f i v) S}
theorem dioph.dioph_comp {α : Type} {n : } {S : set (vector3 n)} (d : dioph S) (f : vector3 ((α → )) n) (df : vector_allp dioph.dioph_fn f) :
dioph {v : α → | (λ (i : fin2 n), f i v) S}
theorem dioph.dioph_fn_comp {α : Type} {n : } {f : vector3 n} (df : dioph.dioph_fn f) (g : vector3 ((α → )) n) (dg : vector_allp dioph.dioph_fn g) :
dioph.dioph_fn (λ (v : α → ), f (λ (i : fin2 n), g i v))
theorem dioph.proj_dioph_of_nat {n : } (m : ) [fin2.is_lt m n] :
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 : vector3 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 : vector3 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 : vector3 4), ∃ (h : 1 < v (fin2.of_nat' 0)), pell.xn h (v (fin2.of_nat' 1)) = v (fin2.of_nat' 2) pell.yn h (v (fin2.of_nat' 1)) = v (fin2.of_nat' 3))
theorem dioph.xn_dioph  :
dioph.dioph_pfun (λ (v : vector3 2), {dom := 1 < v (fin2.of_nat' 0), get := λ (h : 1 < v (fin2.of_nat' 0)), pell.xn h (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