l3lab/ntp-mathlib huggingface dataset:
/-- An encodable type is equivalent to the range of its encoding function. -/
def equivRangeEncode (α : Type*) [Encodable α] : α ≃ Set.range (@encode α _)
    where
  toFun := fun a : α => ⟨encode a, Set.mem_range_self _⟩
  invFun n :=
    Option.get _
      (show isSome (decode₂ α n.1) by cases' n.2 with x hx; rw [← hx, encodek₂]; exact rfl)
  left_inv a := by dsimp; rw [← Option.some_inj, Option.some_get, encodek₂]
  right_inv := fun ⟨n, x, hx⟩ => by
    apply Subtype.eq
    dsimp
    conv =>
      

Proof state:
α✝ : Type u_1
β : Type u_2
α : Type u_3
inst✝ : Encodable α
x✝ : ↑(Set.range encode)
n : ℕ
x : α
hx : encode x = n
| encode (Option.get (decode₂ α n) (_ : isSome (decode₂ α n) = true)) = n

Next tactic:
rhs
      rw [← hx]
/-- An encodable type is equivalent to the range of its encoding function. -/
def equivRangeEncode (α : Type*) [Encodable α] : α ≃ Set.range (@encode α _)
    where
  toFun := fun a : α => ⟨encode a, Set.mem_range_self _⟩
  invFun n :=
    Option.get _
      (show isSome (decode₂ α n.1) by cases' n.2 with x hx; rw [← hx, encodek₂]; exact rfl)
  left_inv a := by dsimp; rw [← Option.some_inj, Option.some_get, encodek₂]
  right_inv := fun ⟨n, x, hx⟩ => by
    apply Subtype.eq
    dsimp
    conv =>
      

Proof state:
α✝ : Type u_1
β : Type u_2
α : Type u_3
inst✝ : Encodable α
x✝ : ↑(Set.range encode)
n : ℕ
x : α
hx : encode x = n
| encode (Option.get (decode₂ α n) (_ : isSome (decode₂ α n) = true)) = n

Next tactic:
rhs
/-- An encodable type is equivalent to the range of its encoding function. -/
def equivRangeEncode (α : Type*) [Encodable α] : α ≃ Set.range (@encode α _)
    where
  toFun := fun a : α => ⟨encode a, Set.mem_range_self _⟩
  invFun n :=
    Option.get _
      (show isSome (decode₂ α n.1) by cases' n.2 with x hx; rw [← hx, encodek₂]; exact rfl)
  left_inv a := by dsimp; rw [← Option.some_inj, Option.some_get, encodek₂]
  right_inv := fun ⟨n, x, hx⟩ => by
    apply Subtype.eq
    dsimp
    conv =>
      rhs
      

Proof state:
α✝ : Type u_1
β : Type u_2
α : Type u_3
inst✝ : Encodable α
x✝ : ↑(Set.range encode)
n : ℕ
x : α
hx : encode x = n
| n

Next tactic:
rw [← hx]
/-- An encodable type is equivalent to the range of its encoding function. -/
def equivRangeEncode (α : Type*) [Encodable α] : α ≃ Set.range (@encode α _)
    where
  toFun := fun a : α => ⟨encode a, Set.mem_range_self _⟩
  invFun n :=
    Option.get _
      (show isSome (decode₂ α n.1) by cases' n.2 with x hx; rw [← hx, encodek₂]; exact rfl)
  left_inv a := by dsimp; rw [← Option.some_inj, Option.some_get, encodek₂]
  right_inv := fun ⟨n, x, hx⟩ => by
    apply Subtype.eq
    dsimp
    conv =>
      rhs
      rw [← hx]
    

Proof state:
case a
α✝ : Type u_1
β : Type u_2
α : Type u_3
inst✝ : Encodable α
x✝ : ↑(Set.range encode)
n : ℕ
x : α
hx : encode x = n
⊢ encode (Option.get (decode₂ α n) (_ : isSome (decode₂ α n) = true)) = encode x

Next tactic:
rw [encode_injective.eq_iff, ← Option.some_inj, Option.some_get, ← hx, encodek₂]
/-- If `α` and `β` are encodable, then so is their sum. -/
instance _root_.Sum.encodable : Encodable (Sum α β) :=
  ⟨encodeSum, decodeSum, fun s => by 

Proof state:
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Encodable β
s : α ⊕ β
⊢ decodeSum (encodeSum s) = some s

Next tactic:
cases s
/-- If `α` and `β` are encodable, then so is their sum. -/
instance _root_.Sum.encodable : Encodable (Sum α β) :=
  ⟨encodeSum, decodeSum, fun s => by cases s <;> 

Proof state:
case inl
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Encodable β
val✝ : α
⊢ decodeSum (encodeSum (Sum.inl val✝)) = some (Sum.inl val✝)

Next tactic:
simp [encodeSum, div2_val, decodeSum, encodek]
/-- If `α` and `β` are encodable, then so is their sum. -/
instance _root_.Sum.encodable : Encodable (Sum α β) :=
  ⟨encodeSum, decodeSum, fun s => by cases s <;> 

Proof state:
case inr
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Encodable β
val✝ : β
⊢ decodeSum (encodeSum (Sum.inr val✝)) = some (Sum.inr val✝)

Next tactic:
simp [encodeSum, div2_val, decodeSum, encodek]
theorem decode_ge_two (n) (h : 2 ≤ n) : (decode n : Option Bool) = none := by
  

Proof state:
α : Type u_1
β : Type u_2
n : ℕ
h : 2 ≤ n
⊢ decode n = none

Next tactic:
suffices decodeSum n = none by
    change (decodeSum n).bind _ = none
    rw [this]
    rfl
theorem decode_ge_two (n) (h : 2 ≤ n) : (decode n : Option Bool) = none := by
  suffices decodeSum n = none by
    

Proof state:
α : Type u_1
β : Type u_2
n : ℕ
h : 2 ≤ n
this : decodeSum n = none
⊢ decode n = none

Next tactic:
change (decodeSum n).bind _ = none
theorem decode_ge_two (n) (h : 2 ≤ n) : (decode n : Option Bool) = none := by
  suffices decodeSum n = none by
    change (decodeSum n).bind _ = none
    

Proof state:
α : Type u_1
β : Type u_2
n : ℕ
h : 2 ≤ n
this : decodeSum n = none
⊢ Option.bind (decodeSum n) (some ∘ ⇑Equiv.boolEquivPUnitSumPUnit.symm) = none

Next tactic:
rw [this]
theorem decode_ge_two (n) (h : 2 ≤ n) : (decode n : Option Bool) = none := by
  suffices decodeSum n = none by
    change (decodeSum n).bind _ = none
    rw [this]
    

Proof state:
α : Type u_1
β : Type u_2
n : ℕ
h : 2 ≤ n
this : decodeSum n = none
⊢ Option.bind none (some ∘ ⇑Equiv.boolEquivPUnitSumPUnit.symm) = none

Next tactic:
rfl
theorem decode_ge_two (n) (h : 2 ≤ n) : (decode n : Option Bool) = none := by
  suffices decodeSum n = none by
    change (decodeSum n).bind _ = none
    rw [this]
    rfl
  

Proof state:
α : Type u_1
β : Type u_2
n : ℕ
h : 2 ≤ n
⊢ decodeSum n = none

Next tactic:
have : 1 ≤ n / 2 := by
    rw [Nat.le_div_iff_mul_le]
    exacts [h, by decide]
theorem decode_ge_two (n) (h : 2 ≤ n) : (decode n : Option Bool) = none := by
  suffices decodeSum n = none by
    change (decodeSum n).bind _ = none
    rw [this]
    rfl
  have : 1 ≤ n / 2 := by
    

Proof state:
α : Type u_1
β : Type u_2
n : ℕ
h : 2 ≤ n
⊢ 1 ≤ n / 2

Next tactic:
rw [Nat.le_div_iff_mul_le]
theorem decode_ge_two (n) (h : 2 ≤ n) : (decode n : Option Bool) = none := by
  suffices decodeSum n = none by
    change (decodeSum n).bind _ = none
    rw [this]
    rfl
  have : 1 ≤ n / 2 := by
    rw [Nat.le_div_iff_mul_le]
    

Proof state:
α : Type u_1
β : Type u_2
n : ℕ
h : 2 ≤ n
⊢ 1 * 2 ≤ n
α : Type u_1 β : Type u_2 n : ℕ h : 2 ≤ n ⊢ 0 < 2

Next tactic:
exacts [h, by decide]
theorem decode_ge_two (n) (h : 2 ≤ n) : (decode n : Option Bool) = none := by
  suffices decodeSum n = none by
    change (decodeSum n).bind _ = none
    rw [this]
    rfl
  have : 1 ≤ n / 2 := by
    rw [Nat.le_div_iff_mul_le]
    exacts [h, by 

Proof state:
α : Type u_1
β : Type u_2
n : ℕ
h : 2 ≤ n
⊢ 0 < 2

Next tactic:
decide
theorem decode_ge_two (n) (h : 2 ≤ n) : (decode n : Option Bool) = none := by
  suffices decodeSum n = none by
    change (decodeSum n).bind _ = none
    rw [this]
    rfl
  have : 1 ≤ n / 2 := by
    rw [Nat.le_div_iff_mul_le]
    exacts [h, by decide]
  

Proof state:
α : Type u_1
β : Type u_2
n : ℕ
h : 2 ≤ n
this : 1 ≤ n / 2
⊢ decodeSum n = none

Next tactic:
cases' exists_eq_succ_of_ne_zero (_root_.ne_of_gt this) with m e
theorem decode_ge_two (n) (h : 2 ≤ n) : (decode n : Option Bool) = none := by
  suffices decodeSum n = none by
    change (decodeSum n).bind _ = none
    rw [this]
    rfl
  have : 1 ≤ n / 2 := by
    rw [Nat.le_div_iff_mul_le]
    exacts [h, by decide]
  cases' exists_eq_succ_of_ne_zero (_root_.ne_of_gt this) with m e
  

Proof state:
case intro
α : Type u_1
β : Type u_2
n : ℕ
h : 2 ≤ n
this : 1 ≤ n / 2
m : ℕ
e : n / 2 = succ m
⊢ decodeSum n = none

Next tactic:
simp [decodeSum, div2_val]
theorem decode_ge_two (n) (h : 2 ≤ n) : (decode n : Option Bool) = none := by
  suffices decodeSum n = none by
    change (decodeSum n).bind _ = none
    rw [this]
    rfl
  have : 1 ≤ n / 2 := by
    rw [Nat.le_div_iff_mul_le]
    exacts [h, by decide]
  cases' exists_eq_succ_of_ne_zero (_root_.ne_of_gt this) with m e
  simp [decodeSum, div2_val]; 

Proof state:
case intro
α : Type u_1
β : Type u_2
n : ℕ
h : 2 ≤ n
this : 1 ≤ n / 2
m : ℕ
e : n / 2 = succ m
⊢ (match (bodd n, n / 2) with
    | (false, m) => Option.map Sum.inl (decode m)
    | (fst, m) => Option.map Sum.inr (decode m)) =
    none

Next tactic:
cases bodd n
theorem decode_ge_two (n) (h : 2 ≤ n) : (decode n : Option Bool) = none := by
  suffices decodeSum n = none by
    change (decodeSum n).bind _ = none
    rw [this]
    rfl
  have : 1 ≤ n / 2 := by
    rw [Nat.le_div_iff_mul_le]
    exacts [h, by decide]
  cases' exists_eq_succ_of_ne_zero (_root_.ne_of_gt this) with m e
  simp [decodeSum, div2_val]; cases bodd n <;> 

Proof state:
case intro.false
α : Type u_1
β : Type u_2
n : ℕ
h : 2 ≤ n
this : 1 ≤ n / 2
m : ℕ
e : n / 2 = succ m
⊢ (match (false, n / 2) with
    | (false, m) => Option.map Sum.inl (decode m)
    | (fst, m) => Option.map Sum.inr (decode m)) =
    none

Next tactic:
simp [e]
theorem decode_ge_two (n) (h : 2 ≤ n) : (decode n : Option Bool) = none := by
  suffices decodeSum n = none by
    change (decodeSum n).bind _ = none
    rw [this]
    rfl
  have : 1 ≤ n / 2 := by
    rw [Nat.le_div_iff_mul_le]
    exacts [h, by decide]
  cases' exists_eq_succ_of_ne_zero (_root_.ne_of_gt this) with m e
  simp [decodeSum, div2_val]; cases bodd n <;> 

Proof state:
case intro.true
α : Type u_1
β : Type u_2
n : ℕ
h : 2 ≤ n
this : 1 ≤ n / 2
m : ℕ
e : n / 2 = succ m
⊢ (match (true, n / 2) with
    | (false, m) => Option.map Sum.inl (decode m)
    | (fst, m) => Option.map Sum.inr (decode m)) =
    none

Next tactic:
simp [e]
instance _root_.Sigma.encodable : Encodable (Sigma γ) :=
  ⟨encodeSigma, decodeSigma, fun ⟨a, b⟩ => by
    

Proof state:
α : Type u_1
β : Type u_2
γ : α → Type u_3
inst✝¹ : Encodable α
inst✝ : (a : α) → Encodable (γ a)
x✝ : Sigma γ
a : α
b : γ a
⊢ decodeSigma (encodeSigma { fst := a, snd := b }) = some { fst := a, snd := b }

Next tactic:
simp [encodeSigma, decodeSigma, unpair_pair, encodek]
@[simp]
theorem decode_prod_val [i : Encodable α] (n : ℕ) :
    (@decode (α × β) _ n : Option (α × β))
      = (decode n.unpair.1).bind fun a => (decode n.unpair.2).map <| Prod.mk a := by
  

Proof state:
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Encodable β
i : Encodable α
n : ℕ
⊢ decode n = Option.bind (decode (unpair n).1) fun a => Option.map (Prod.mk a) (decode (unpair n).2)

Next tactic:
simp only [decode_ofEquiv, Equiv.symm_symm, decode_sigma_val]
@[simp]
theorem decode_prod_val [i : Encodable α] (n : ℕ) :
    (@decode (α × β) _ n : Option (α × β))
      = (decode n.unpair.1).bind fun a => (decode n.unpair.2).map <| Prod.mk a := by
  simp only [decode_ofEquiv, Equiv.symm_symm, decode_sigma_val]
  

Proof state:
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Encodable β
i : Encodable α
n : ℕ
⊢ Option.map (⇑(Equiv.sigmaEquivProd α β))
      (Option.bind (decode (unpair n).1) fun a => Option.map (Sigma.mk a) (decode (unpair n).2)) =
    Option.bind (decode (unpair n).1) fun a => Option.map (Prod.mk a) (decode (unpair n).2)

Next tactic:
cases (decode n.unpair.1 : Option α)
@[simp]
theorem decode_prod_val [i : Encodable α] (n : ℕ) :
    (@decode (α × β) _ n : Option (α × β))
      = (decode n.unpair.1).bind fun a => (decode n.unpair.2).map <| Prod.mk a := by
  simp only [decode_ofEquiv, Equiv.symm_symm, decode_sigma_val]
  cases (decode n.unpair.1 : Option α) <;> 

Proof state:
case none
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Encodable β
i : Encodable α
n : ℕ
⊢ Option.map (⇑(Equiv.sigmaEquivProd α β)) (Option.bind none fun a => Option.map (Sigma.mk a) (decode (unpair n).2)) =
    Option.bind none fun a => Option.map (Prod.mk a) (decode (unpair n).2)

Next tactic:
cases (decode n.unpair.2 : Option β)
@[simp]
theorem decode_prod_val [i : Encodable α] (n : ℕ) :
    (@decode (α × β) _ n : Option (α × β))
      = (decode n.unpair.1).bind fun a => (decode n.unpair.2).map <| Prod.mk a := by
  simp only [decode_ofEquiv, Equiv.symm_symm, decode_sigma_val]
  cases (decode n.unpair.1 : Option α) <;> 

Proof state:
case some
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Encodable β
i : Encodable α
n : ℕ
val✝ : α
⊢ Option.map (⇑(Equiv.sigmaEquivProd α β))
      (Option.bind (some val✝) fun a => Option.map (Sigma.mk a) (decode (unpair n).2)) =
    Option.bind (some val✝) fun a => Option.map (Prod.mk a) (decode (unpair n).2)

Next tactic:
cases (decode n.unpair.2 : Option β)
@[simp]
theorem decode_prod_val [i : Encodable α] (n : ℕ) :
    (@decode (α × β) _ n : Option (α × β))
      = (decode n.unpair.1).bind fun a => (decode n.unpair.2).map <| Prod.mk a := by
  simp only [decode_ofEquiv, Equiv.symm_symm, decode_sigma_val]
  cases (decode n.unpair.1 : Option α) <;> cases (decode n.unpair.2 : Option β)
  <;> 

Proof state:
case none.none
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Encodable β
i : Encodable α
n : ℕ
⊢ Option.map (⇑(Equiv.sigmaEquivProd α β)) (Option.bind none fun a => Option.map (Sigma.mk a) none) =
    Option.bind none fun a => Option.map (Prod.mk a) none

Next tactic:
rfl
@[simp]
theorem decode_prod_val [i : Encodable α] (n : ℕ) :
    (@decode (α × β) _ n : Option (α × β))
      = (decode n.unpair.1).bind fun a => (decode n.unpair.2).map <| Prod.mk a := by
  simp only [decode_ofEquiv, Equiv.symm_symm, decode_sigma_val]
  cases (decode n.unpair.1 : Option α) <;> cases (decode n.unpair.2 : Option β)
  <;> 

Proof state:
case none.some
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Encodable β
i : Encodable α
n : ℕ
val✝ : β
⊢ Option.map (⇑(Equiv.sigmaEquivProd α β)) (Option.bind none fun a => Option.map (Sigma.mk a) (some val✝)) =
    Option.bind none fun a => Option.map (Prod.mk a) (some val✝)

Next tactic:
rfl
@[simp]
theorem decode_prod_val [i : Encodable α] (n : ℕ) :
    (@decode (α × β) _ n : Option (α × β))
      = (decode n.unpair.1).bind fun a => (decode n.unpair.2).map <| Prod.mk a := by
  simp only [decode_ofEquiv, Equiv.symm_symm, decode_sigma_val]
  cases (decode n.unpair.1 : Option α) <;> cases (decode n.unpair.2 : Option β)
  <;> 

Proof state:
case some.none
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Encodable β
i : Encodable α
n : ℕ
val✝ : α
⊢ Option.map (⇑(Equiv.sigmaEquivProd α β)) (Option.bind (some val✝) fun a => Option.map (Sigma.mk a) none) =
    Option.bind (some val✝) fun a => Option.map (Prod.mk a) none

Next tactic:
rfl
@[simp]
theorem decode_prod_val [i : Encodable α] (n : ℕ) :
    (@decode (α × β) _ n : Option (α × β))
      = (decode n.unpair.1).bind fun a => (decode n.unpair.2).map <| Prod.mk a := by
  simp only [decode_ofEquiv, Equiv.symm_symm, decode_sigma_val]
  cases (decode n.unpair.1 : Option α) <;> cases (decode n.unpair.2 : Option β)
  <;> 

Proof state:
case some.some
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Encodable β
i : Encodable α
n : ℕ
val✝¹ : α
val✝ : β
⊢ Option.map (⇑(Equiv.sigmaEquivProd α β)) (Option.bind (some val✝¹) fun a => Option.map (Sigma.mk a) (some val✝)) =
    Option.bind (some val✝¹) fun a => Option.map (Prod.mk a) (some val✝)

Next tactic:
rfl
/-- A decidable subtype of an encodable type is encodable. -/
instance _root_.Subtype.encodable : Encodable { a : α // P a } :=
  ⟨encodeSubtype, decodeSubtype, fun ⟨v, h⟩ => by 

Proof state:
α : Type u_1
β : Type u_2
P : α → Prop
encA : Encodable α
decP : DecidablePred P
x✝ : { a // P a }
v : α
h : P v
⊢ decodeSubtype (encodeSubtype { val := v, property := h }) = some { val := v, property := h }

Next tactic:
simp [encodeSubtype, decodeSubtype, encodek, h]
theorem Subtype.encode_eq (a : Subtype P) : encode a = encode a.val := by 

Proof state:
α : Type u_1
β : Type u_2
P : α → Prop
encA : Encodable α
decP : DecidablePred P
a : Subtype P
⊢ encode a = encode ↑a

Next tactic:
cases a
theorem Subtype.encode_eq (a : Subtype P) : encode a = encode a.val := by cases a; 

Proof state:
case mk
α : Type u_1
β : Type u_2
P : α → Prop
encA : Encodable α
decP : DecidablePred P
val✝ : α
property✝ : P val✝
⊢ encode { val := val✝, property := property✝ } = encode ↑{ val := val✝, property := property✝ }

Next tactic:
rfl
instance : Countable ℕ+ := by 

Proof state:
⊢ Countable ℕ+

Next tactic:
delta PNat
instance : Countable ℕ+ := by delta PNat; 

Proof state:
⊢ Countable { n // 0 < n }

Next tactic:
infer_instance
instance {α : Type*} [Encodable α] : DecidableEq (ULower α) :=
  by 

Proof state:
α : Type u_1
inst✝ : Encodable α
⊢ DecidableEq (ULower α)

Next tactic:
delta ULower
instance {α : Type*} [Encodable α] : DecidableEq (ULower α) :=
  by delta ULower; 

Proof state:
α : Type u_1
inst✝ : Encodable α
⊢ DecidableEq ↑(Set.range Encodable.encode)

Next tactic:
exact Encodable.decidableEqOfEncodable _
instance {α : Type*} [Encodable α] : Encodable (ULower α) :=
  by 

Proof state:
α : Type u_1
inst✝ : Encodable α
⊢ Encodable (ULower α)

Next tactic:
delta ULower
instance {α : Type*} [Encodable α] : Encodable (ULower α) :=
  by delta ULower; 

Proof state:
α : Type u_1
inst✝ : Encodable α
⊢ Encodable ↑(Set.range Encodable.encode)

Next tactic:
infer_instance
@[simp]
theorem up_down {a : α} : (down a).up = a := by
  

Proof state:
α : Type u_1
inst✝ : Encodable α
a : α
⊢ up (down a) = a

Next tactic:
simp [up, down,Equiv.left_inv _ _, Equiv.symm_apply_apply]
private def decidable_good : DecidablePred (good p) :=
  fun n => by
    

Proof state:
α : Type u_1
p : α → Prop
inst✝¹ : Encodable α
inst✝ : DecidablePred p
n : Option α
⊢ Decidable (Encodable.good p n)

Next tactic:
cases n
private def decidable_good : DecidablePred (good p) :=
  fun n => by
    cases n <;> 

Proof state:
case none
α : Type u_1
p : α → Prop
inst✝¹ : Encodable α
inst✝ : DecidablePred p
⊢ Decidable (Encodable.good p none)

Next tactic:
unfold good
private def decidable_good : DecidablePred (good p) :=
  fun n => by
    cases n <;> 

Proof state:
case some
α : Type u_1
p : α → Prop
inst✝¹ : Encodable α
inst✝ : DecidablePred p
val✝ : α
⊢ Decidable (Encodable.good p (some val✝))

Next tactic:
unfold good
private def decidable_good : DecidablePred (good p) :=
  fun n => by
    cases n <;> unfold good <;> 

Proof state:
case none
α : Type u_1
p : α → Prop
inst✝¹ : Encodable α
inst✝ : DecidablePred p
⊢ Decidable
    (match none with
    | some a => p a
    | none => False)

Next tactic:
dsimp
private def decidable_good : DecidablePred (good p) :=
  fun n => by
    cases n <;> unfold good <;> 

Proof state:
case some
α : Type u_1
p : α → Prop
inst✝¹ : Encodable α
inst✝ : DecidablePred p
val✝ : α
⊢ Decidable
    (match some val✝ with
    | some a => p a
    | none => False)

Next tactic:
dsimp
private def decidable_good : DecidablePred (good p) :=
  fun n => by
    cases n <;> unfold good <;> dsimp <;> 

Proof state:
case none
α : Type u_1
p : α → Prop
inst✝¹ : Encodable α
inst✝ : DecidablePred p
⊢ Decidable False

Next tactic:
infer_instance
private def decidable_good : DecidablePred (good p) :=
  fun n => by
    cases n <;> unfold good <;> dsimp <;> 

Proof state:
case some
α : Type u_1
p : α → Prop
inst✝¹ : Encodable α
inst✝ : DecidablePred p
val✝ : α
⊢ Decidable (p val✝)

Next tactic:
infer_instance
/-- Constructive choice function for a decidable subtype of an encodable type. -/
def chooseX (h : ∃ x, p x) : { a : α // p a } :=
  have : ∃ n, good p (decode n) :=
    let ⟨w, pw⟩ := h
    ⟨encode w, by 

Proof state:
α : Type u_1
p : α → Prop
inst✝¹ : Encodable α
inst✝ : DecidablePred p
h : ∃ x, p x
w : α
pw : p w
⊢ Encodable.good p (decode (encode w))

Next tactic:
simp [good, encodek, pw]
theorem sequence_mono_nat {r : β → β → Prop} {f : α → β} (hf : Directed r f) (n : ℕ) :
    r (f (hf.sequence f n)) (f (hf.sequence f (n + 1))) := by
  

Proof state:
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Inhabited α
r : β → β → Prop
f : α → β
hf : Directed r f
n : ℕ
⊢ r (f (Directed.sequence f hf n)) (f (Directed.sequence f hf (n + 1)))

Next tactic:
dsimp [Directed.sequence]
theorem sequence_mono_nat {r : β → β → Prop} {f : α → β} (hf : Directed r f) (n : ℕ) :
    r (f (hf.sequence f n)) (f (hf.sequence f (n + 1))) := by
  dsimp [Directed.sequence]
  

Proof state:
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Inhabited α
r : β → β → Prop
f : α → β
hf : Directed r f
n : ℕ
⊢ r (f (Directed.sequence f hf n))
    (f
      (match decode n with
      | none =>
        Classical.choose (_ : ∃ z, r (f (Directed.sequence f hf n)) (f z) ∧ r (f (Directed.sequence f hf n)) (f z))
      | some a => Classical.choose (_ : ∃ z, r (f (Directed.sequence f hf n)) (f z) ∧ r (f a) (f z))))

Next tactic:
generalize hf.sequence f n = p
theorem sequence_mono_nat {r : β → β → Prop} {f : α → β} (hf : Directed r f) (n : ℕ) :
    r (f (hf.sequence f n)) (f (hf.sequence f (n + 1))) := by
  dsimp [Directed.sequence]
  generalize hf.sequence f n = p
  

Proof state:
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Inhabited α
r : β → β → Prop
f : α → β
hf : Directed r f
n : ℕ
p : α
⊢ r (f p)
    (f
      (match decode n with
      | none => Classical.choose (_ : ∃ z, r (f p) (f z) ∧ r (f p) (f z))
      | some a => Classical.choose (_ : ∃ z, r (f p) (f z) ∧ r (f a) (f z))))

Next tactic:
cases' h : (decode n: Option α) with a
theorem sequence_mono_nat {r : β → β → Prop} {f : α → β} (hf : Directed r f) (n : ℕ) :
    r (f (hf.sequence f n)) (f (hf.sequence f (n + 1))) := by
  dsimp [Directed.sequence]
  generalize hf.sequence f n = p
  cases' h : (decode n: Option α) with a
  · 

Proof state:
case none
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Inhabited α
r : β → β → Prop
f : α → β
hf : Directed r f
n : ℕ
p : α
h : decode n = none
⊢ r (f p)
    (f
      (match none with
      | none => Classical.choose (_ : ∃ z, r (f p) (f z) ∧ r (f p) (f z))
      | some a => Classical.choose (_ : ∃ z, r (f p) (f z) ∧ r (f a) (f z))))

Next tactic:
exact (Classical.choose_spec (hf p p)).1
theorem sequence_mono_nat {r : β → β → Prop} {f : α → β} (hf : Directed r f) (n : ℕ) :
    r (f (hf.sequence f n)) (f (hf.sequence f (n + 1))) := by
  dsimp [Directed.sequence]
  generalize hf.sequence f n = p
  cases' h : (decode n: Option α) with a
  · exact (Classical.choose_spec (hf p p)).1
  · 

Proof state:
case some
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Inhabited α
r : β → β → Prop
f : α → β
hf : Directed r f
n : ℕ
p a : α
h : decode n = some a
⊢ r (f p)
    (f
      (match some a with
      | none => Classical.choose (_ : ∃ z, r (f p) (f z) ∧ r (f p) (f z))
      | some a => Classical.choose (_ : ∃ z, r (f p) (f z) ∧ r (f a) (f z))))

Next tactic:
exact (Classical.choose_spec (hf p a)).1
theorem rel_sequence {r : β → β → Prop} {f : α → β} (hf : Directed r f) (a : α) :
    r (f a) (f (hf.sequence f (encode a + 1))) := by
  

Proof state:
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Inhabited α
r : β → β → Prop
f : α → β
hf : Directed r f
a : α
⊢ r (f a) (f (Directed.sequence f hf (encode a + 1)))

Next tactic:
simp only [Directed.sequence, add_eq, add_zero, encodek, and_self]
theorem rel_sequence {r : β → β → Prop} {f : α → β} (hf : Directed r f) (a : α) :
    r (f a) (f (hf.sequence f (encode a + 1))) := by
  simp only [Directed.sequence, add_eq, add_zero, encodek, and_self]
  

Proof state:
α : Type u_1
β : Type u_2
inst✝¹ : Encodable α
inst✝ : Inhabited α
r : β → β → Prop
f : α → β
hf : Directed r f
a : α
⊢ r (f a) (f (Classical.choose (_ : ∃ x, (fun x => r (f (Directed.sequence f hf (encode a))) (f x) ∧ r (f a) (f x)) x)))

Next tactic:
exact (Classical.choose_spec (hf _ a)).2
/-- The quotient of an encodable space by a decidable equivalence relation is encodable. -/
def encodableQuotient : Encodable (Quotient s) :=
  ⟨fun q => encode q.rep, fun n => Quotient.mk'' <$> decode n, by
    

Proof state:
α : Type u_1
s : Setoid α
inst✝¹ : DecidableRel fun x x_1 => x ≈ x_1
inst✝ : Encodable α
⊢ ∀ (a : Quotient s), (fun n => Quotient.mk'' <$> decode n) ((fun q => encode (rep q)) a) = some a

Next tactic:
rintro ⟨l⟩
/-- The quotient of an encodable space by a decidable equivalence relation is encodable. -/
def encodableQuotient : Encodable (Quotient s) :=
  ⟨fun q => encode q.rep, fun n => Quotient.mk'' <$> decode n, by
    rintro ⟨l⟩; 

Proof state:
case mk
α : Type u_1
s : Setoid α
inst✝¹ : DecidableRel fun x x_1 => x ≈ x_1
inst✝ : Encodable α
a✝ : Quotient s
l : α
⊢ (fun n => Quotient.mk'' <$> decode n) ((fun q => encode (rep q)) (Quot.mk Setoid.r l)) = some (Quot.mk Setoid.r l)

Next tactic:
dsimp