# Documentation

Mathlib.Logic.Encodable.Basic

# Encodable types #

This file defines encodable (constructively countable) types as a typeclass. This is used to provide explicit encode/decode functions from and to ℕ, with the information that those functions are inverses of each other. The difference with Denumerable is that finite types are encodable. For infinite types, Encodable and Denumerable agree.

## Main declarations #

• Encodable α: States that there exists an explicit encoding function encode : α → ℕ with a partial inverse decode : ℕ → Option α.
• decode₂: Version of decode that is equal to none outside of the range of encode. Useful as we do not require this in the definition of decode.
• ulower α: Any encodable type has an equivalent type living in the lowest universe, namely a subtype of ℕ. ulower α finds it.

## Implementation notes #

The point of asking for an explicit partial inverse decode : ℕ → Option α to encode : α → ℕ is to make the range of encode decidable even when the finiteness of α is not.

class Encodable (α : Type u_1) :
Type u_1
• Encoding from Type α to ℕ

encode : α
• Decoding from ℕ to Option α

decode :
• Invariant relationship between encoding and decoding

encodek : ∀ (a : α), decode (encode a) = some a

Constructively countable type. Made from an explicit injection encode : α → ℕ and a partial inverse decode : ℕ → Option α. Note that finite types are countable. See Denumerable if you wish to enforce infiniteness.

Instances
theorem Encodable.encode_injective {α : Type u_1} [inst : ] :
Function.Injective Encodable.encode
@[simp]
theorem Encodable.encode_inj {α : Type u_1} [inst : ] {a : α} {b : α} :
a = b
instance Encodable.countable {α : Type u_1} [inst : ] :
Equations
theorem Encodable.surjective_decode_iget (α : Type u_1) [inst : ] [inst : ] :
def Encodable.decidableEqOfEncodable (α : Type u_1) [inst : ] :

An encodable type has decidable equality. Not set as an instance because this is usually not the best way to infer decidability.

Equations
• One or more equations did not get rendered due to their size.
def Encodable.ofLeftInjection {α : Type u_1} {β : Type u_2} [inst : ] (f : βα) (finv : α) (linv : ∀ (b : β), finv (f b) = some b) :

If α is encodable and there is an injection f : β → α, then β is encodable as well.

Equations
• One or more equations did not get rendered due to their size.
def Encodable.ofLeftInverse {α : Type u_1} {β : Type u_2} [inst : ] (f : βα) (finv : αβ) (linv : ∀ (b : β), finv (f b) = b) :

If α is encodable and f : β → α is invertible, then β is encodable as well.

Equations
def Encodable.ofEquiv {β : Type u_1} (α : Type u_2) [inst : ] (e : β α) :

Encodability is preserved by equivalence.

Equations
theorem Encodable.encode_ofEquiv {α : Type u_1} {β : Type u_2} [inst : ] (e : β α) (b : β) :
theorem Encodable.decode_ofEquiv {α : Type u_1} {β : Type u_2} [inst : ] (e : β α) (n : ) :
= Option.map (↑()) ()
Equations
@[simp]
theorem Encodable.encode_nat (n : ) :
@[simp]
theorem Encodable.decode_nat (n : ) :
instance Encodable.IsEmpty.toEncodable {α : Type u_1} [inst : ] :
Equations
• Encodable.IsEmpty.toEncodable = { encode := fun a => , decode := fun x => none, encodek := (_ : ∀ (a : α), (fun x => none) ((fun a => ) a) = some a) }
Equations
@[simp]
@[simp]
theorem Encodable.decode_unit_succ (n : ) :
= none
instance Option.encodable {α : Type u_1} [h : ] :

If α is encodable, then so is Option α.

Equations
• One or more equations did not get rendered due to their size.
@[simp]
theorem Encodable.encode_none {α : Type u_1} [inst : ] :
@[simp]
theorem Encodable.encode_some {α : Type u_1} [inst : ] (a : α) :
@[simp]
theorem Encodable.decode_option_zero {α : Type u_1} [inst : ] :
= some none
@[simp]
theorem Encodable.decode_option_succ {α : Type u_1} [inst : ] (n : ) :
= Option.map some ()
def Encodable.decode₂ (α : Type u_1) [inst : ] (n : ) :

Failsafe variant of decode. decode₂ α n returns the preimage of n under encode if it exists, and returns none if it doesn't. This requirement could be imposed directly on decode but is not to help make the definition easier to use.

Equations
theorem Encodable.mem_decode₂' {α : Type u_1} [inst : ] {n : } {a : α} :
theorem Encodable.mem_decode₂ {α : Type u_1} [inst : ] {n : } {a : α} :
a
theorem Encodable.decode₂_eq_some {α : Type u_1} [inst : ] {n : } {a : α} :
= some a
@[simp]
theorem Encodable.decode₂_encode {α : Type u_1} [inst : ] (a : α) :
theorem Encodable.decode₂_ne_none_iff {α : Type u_1} [inst : ] {n : } :
none n Set.range Encodable.encode
theorem Encodable.decode₂_is_partial_inv {α : Type u_1} [inst : ] :
Function.IsPartialInv Encodable.encode ()
theorem Encodable.decode₂_inj {α : Type u_1} [inst : ] {n : } {a₁ : α} {a₂ : α} (h₁ : a₁ ) (h₂ : a₂ ) :
a₁ = a₂
theorem Encodable.encodek₂ {α : Type u_1} [inst : ] (a : α) :
def Encodable.decidableRangeEncode (α : Type u_1) [inst : ] :
DecidablePred fun x => x Set.range Encodable.encode

The encoding function has decidable range.

Equations
• One or more equations did not get rendered due to their size.
def Encodable.equivRangeEncode (α : Type u_1) [inst : ] :
α ↑(Set.range Encodable.encode)

An encodable type is equivalent to the range of its encoding function.

Equations
• One or more equations did not get rendered due to their size.
def Encodable.Unique.encodable {α : Type u_1} [inst : ] :

A type with unique element is encodable. This is not an instance to avoid diamonds.

Equations
• Encodable.Unique.encodable = { encode := fun x => 0, decode := fun x => some default, encodek := (_ : ∀ (a : α), (fun x => some default) ((fun x => 0) a) = some a) }
def Encodable.encodeSum {α : Type u_1} {β : Type u_2} [inst : ] [inst : ] :
α β

Explicit encoding function for the sum of two encodable types.

Equations
• = match x with | => | => + 1
def Encodable.decodeSum {α : Type u_1} {β : Type u_2} [inst : ] [inst : ] (n : ) :
Option (α β)

Explicit decoding function for the sum of two encodable types.

Equations
instance Encodable.Sum.encodable {α : Type u_1} {β : Type u_2} [inst : ] [inst : ] :
Encodable (α β)

If α and β are encodable, then so is their sum.

Equations
• Encodable.Sum.encodable = { encode := Encodable.encodeSum, decode := Encodable.decodeSum, encodek := (_ : ∀ (s : α β), ) }
@[simp]
theorem Encodable.encode_inl {α : Type u_2} {β : Type u_1} [inst : ] [inst : ] (a : α) :
@[simp]
theorem Encodable.encode_inr {α : Type u_2} {β : Type u_1} [inst : ] [inst : ] (b : β) :
= + 1
@[simp]
theorem Encodable.decode_sum_val {α : Type u_1} {β : Type u_2} [inst : ] [inst : ] (n : ) :
theorem Encodable.decode_ge_two (n : ) (h : 2 n) :
= none
noncomputable instance Encodable.Prop.encodable :
Equations
def Encodable.encodeSigma {α : Type u_1} {γ : αType u_2} [inst : ] [inst : (a : α) → Encodable (γ a)] :

Explicit encoding function for Sigma γ

Equations
• = match x with | { fst := a, snd := b } =>
def Encodable.decodeSigma {α : Type u_1} {γ : αType u_2} [inst : ] [inst : (a : α) → Encodable (γ a)] (n : ) :

Explicit decoding function for Sigma γ

Equations
instance Encodable.Sigma.encodable {α : Type u_1} {γ : αType u_2} [inst : ] [inst : (a : α) → Encodable (γ a)] :
Equations
• Encodable.Sigma.encodable = { encode := Encodable.encodeSigma, decode := Encodable.decodeSigma, encodek := (_ : ∀ (x : ), ) }
@[simp]
theorem Encodable.decode_sigma_val {α : Type u_1} {γ : αType u_2} [inst : ] [inst : (a : α) → Encodable (γ a)] (n : ) :
@[simp]
theorem Encodable.encode_sigma_val {α : Type u_2} {γ : αType u_1} [inst : ] [inst : (a : α) → Encodable (γ a)] (a : α) (b : γ a) :
Encodable.encode { fst := a, snd := b } =
instance Encodable.Prod.encodable {α : Type u_1} {β : Type u_2} [inst : ] [inst : ] :
Encodable (α × β)

If α and β are encodable, then so is their product.

Equations
@[simp]
theorem Encodable.decode_prod_val {α : Type u_1} {β : Type u_2} [inst : ] [i : ] (n : ) :
@[simp]
theorem Encodable.encode_prod_val {α : Type u_2} {β : Type u_1} [inst : ] [inst : ] (a : α) (b : β) :
def Encodable.encodeSubtype {α : Type u_1} {P : αProp} [encA : ] :
{ a // P a }

Explicit encoding function for a decidable subtype of an encodable type

Equations
• = match x with | { val := v, property := property } =>
def Encodable.decodeSubtype {α : Type u_1} {P : αProp} [encA : ] [decP : ] (v : ) :
Option { a // P a }

Explicit decoding function for a decidable subtype of an encodable type

Equations
• = Option.bind () fun a => if h : P a then some { val := a, property := h } else none
instance Encodable.Subtype.encodable {α : Type u_1} {P : αProp} [encA : ] [decP : ] :
Encodable { a // P a }

A decidable subtype of an encodable type is encodable.

Equations
• One or more equations did not get rendered due to their size.
theorem Encodable.Subtype.encode_eq {α : Type u_1} {P : αProp} [encA : ] [decP : ] (a : ) :
Equations
instance Encodable.ULift.encodable {α : Type u_1} [inst : ] :

The lift of an encodable type is encodable.

Equations
instance Encodable.PLift.encodable {α : Type u_1} [inst : ] :

The lift of an encodable type is encodable.

Equations
noncomputable def Encodable.ofInj {α : Type u_1} {β : Type u_2} [inst : ] (f : αβ) (hf : ) :

If β is encodable and there is an injection f : α → β, then α is encodable as well.

Equations
noncomputable def Encodable.ofCountable (α : Type u_1) [inst : ] :

If α is countable, then it has a (non-canonical) Encodable structure.

Equations
@[simp]
theorem Encodable.nonempty_encodable {α : Type u_1} :
theorem nonempty_encodable (α : Type u_1) [inst : ] :

See also nonempty_fintype, nonempty_denumerable.

Equations
def Ulower (α : Type u_1) [inst : ] :

ULower α : Type is an equivalent type in the lowest universe, given Encodable α.

Equations
instance instDecidableEqUlower {α : Type u_1} [inst : ] :
Equations
instance instEncodableUlower {α : Type u_1} [inst : ] :
Equations
• instEncodableUlower = id inferInstance
def Ulower.equiv (α : Type u_1) [inst : ] :
α

The equivalence between the encodable type α and Ulower α : Type.

Equations
def Ulower.down {α : Type u_1} [inst : ] (a : α) :

Lowers an a : α into Ulower α.

Equations
• = ↑() a
instance Ulower.instInhabitedUlower {α : Type u_1} [inst : ] [inst : ] :
Equations
• Ulower.instInhabitedUlower = { default := Ulower.down default }
def Ulower.up {α : Type u_1} [inst : ] (a : ) :
α

Lifts an a : Ulower α into α.

Equations
• = ↑() a
@[simp]
theorem Ulower.down_up {α : Type u_1} [inst : ] {a : } :
= a
@[simp]
theorem Ulower.up_down {α : Type u_1} [inst : ] {a : α} :
= a
@[simp]
theorem Ulower.up_eq_up {α : Type u_1} [inst : ] {a : } {b : } :
a = b
@[simp]
theorem Ulower.down_eq_down {α : Type u_1} [inst : ] {a : α} {b : α} :
a = b
theorem Ulower.ext {α : Type u_1} [inst : ] {a : } {b : } :
a = b
def Encodable.chooseX {α : Type u_1} {p : αProp} [inst : ] [inst : ] (h : x, p x) :
{ a // p a }

Constructive choice function for a decidable subtype of an encodable type.

Equations
• One or more equations did not get rendered due to their size.
def Encodable.choose {α : Type u_1} {p : αProp} [inst : ] [inst : ] (h : x, p x) :
α

Constructive choice function for a decidable predicate over an encodable type.

Equations
theorem Encodable.choose_spec {α : Type u_1} {p : αProp} [inst : ] [inst : ] (h : x, p x) :
p ()
theorem Encodable.axiom_of_choice {α : Type u_1} {β : αType u_2} {R : (x : α) → β xProp} [inst : (a : α) → Encodable (β a)] [inst : (x : α) → (y : β x) → Decidable (R x y)] (H : ∀ (x : α), y, R x y) :
f, (x : α) → R x (f x)

A constructive version of Classical.axiom_of_choice for Encodable types.

theorem Encodable.skolem {α : Type u_1} {β : αType u_2} {P : (x : α) → β xProp} [inst : (a : α) → Encodable (β a)] [inst : (x : α) → (y : β x) → Decidable (P x y)] :
(∀ (x : α), y, P x y) f, (x : α) → P x (f x)

A constructive version of Classical.skolem for Encodable types.

def Encodable.encode' (α : Type u_1) [inst : ] :
α

The encode function, viewed as an embedding.

Equations
Equations
• One or more equations did not get rendered due to their size.
Equations
• One or more equations did not get rendered due to their size.
Equations
• One or more equations did not get rendered due to their size.
noncomputable def Directed.sequence {α : Type u_1} {β : Type u_2} [inst : ] [inst : ] {r : ββProp} (f : αβ) (hf : Directed r f) :
α

Given a Directed r function f : α → β defined on an encodable inhabited type, construct a noncomputable sequence such that r (f (x n)) (f (x (n + 1))) and r (f a) (f (x (encode a + 1)).

Equations
theorem Directed.sequence_mono_nat {α : Type u_2} {β : Type u_1} [inst : ] [inst : ] {r : ββProp} {f : αβ} (hf : Directed r f) (n : ) :
r (f ()) (f (Directed.sequence f hf (n + 1)))
theorem Directed.rel_sequence {α : Type u_2} {β : Type u_1} [inst : ] [inst : ] {r : ββProp} {f : αβ} (hf : Directed r f) (a : α) :
r (f a) (f (Directed.sequence f hf ()))
theorem Directed.sequence_mono {α : Type u_2} {β : Type u_1} [inst : ] [inst : ] [inst : ] {f : αβ} (hf : Directed (fun x x_1 => x x_1) f) :
theorem Directed.le_sequence {α : Type u_2} {β : Type u_1} [inst : ] [inst : ] [inst : ] {f : αβ} (hf : Directed (fun x x_1 => x x_1) f) (a : α) :
f a f (Directed.sequence f hf ())
def Quotient.rep {α : Type u_1} {s : } [inst : DecidableRel fun x x_1 => x x_1] [inst : ] (q : ) :
α

Representative of an equivalence class. This is a computable version of quot.out for a setoid on an encodable type.

Equations
theorem Quotient.rep_spec {α : Type u_1} {s : } [inst : DecidableRel fun x x_1 => x x_1] [inst : ] (q : ) :
= q
def encodableQuotient {α : Type u_1} {s : } [inst : DecidableRel fun x x_1 => x x_1] [inst : ] :

The quotient of an encodable space by a decidable equivalence relation is encodable.

Equations
• One or more equations did not get rendered due to their size.