l3lab/ntp-mathlib huggingface dataset:
/--
A presheaf is a sheaf for the Grothendieck topology generated by a union of coverages iff it is a
sheaf for the Grothendieck topology generated by each coverage separately.
-/
theorem isSheaf_sup (K L : Coverage C) (P : Cᵒᵖ ⥤ Type w) :
    (Presieve.IsSheaf ((K ⊔ L).toGrothendieck C)) P ↔
    (Presieve.IsSheaf (K.toGrothendieck C)) P ∧ (Presieve.IsSheaf (L.toGrothendieck C)) P := by
  refine ⟨fun h ↦ ⟨Presieve.isSheaf_of_le _ ((gi C).gc.monotone_l le_sup_left) h,
      Presieve.isSheaf_of_le _ ((gi C).gc.monotone_l le_sup_right) h⟩, fun h ↦ ?_⟩
  rw [isSheaf_coverage, isSheaf_coverage] at h
  rw [isSheaf_coverage]
  

Proof state:
C : Type u_1
inst✝ : Category.{u_2, u_1} C
K L : Coverage C
P : Cᵒᵖ ⥤ Type w
h : (∀ {X : C}, ∀ R ∈ covering K X, IsSheafFor P R) ∧ ∀ {X : C}, ∀ R ∈ covering L X, IsSheafFor P R
⊢ ∀ {X : C}, ∀ R ∈ covering (K ⊔ L) X, IsSheafFor P R

Next tactic:
intro X R hR
/--
A presheaf is a sheaf for the Grothendieck topology generated by a union of coverages iff it is a
sheaf for the Grothendieck topology generated by each coverage separately.
-/
theorem isSheaf_sup (K L : Coverage C) (P : Cᵒᵖ ⥤ Type w) :
    (Presieve.IsSheaf ((K ⊔ L).toGrothendieck C)) P ↔
    (Presieve.IsSheaf (K.toGrothendieck C)) P ∧ (Presieve.IsSheaf (L.toGrothendieck C)) P := by
  refine ⟨fun h ↦ ⟨Presieve.isSheaf_of_le _ ((gi C).gc.monotone_l le_sup_left) h,
      Presieve.isSheaf_of_le _ ((gi C).gc.monotone_l le_sup_right) h⟩, fun h ↦ ?_⟩
  rw [isSheaf_coverage, isSheaf_coverage] at h
  rw [isSheaf_coverage]
  intro X R hR
  

Proof state:
C : Type u_1
inst✝ : Category.{u_2, u_1} C
K L : Coverage C
P : Cᵒᵖ ⥤ Type w
h : (∀ {X : C}, ∀ R ∈ covering K X, IsSheafFor P R) ∧ ∀ {X : C}, ∀ R ∈ covering L X, IsSheafFor P R
X : C
R : Presieve X
hR : R ∈ covering (K ⊔ L) X
⊢ IsSheafFor P R

Next tactic:
cases' hR with hR hR
/--
A presheaf is a sheaf for the Grothendieck topology generated by a union of coverages iff it is a
sheaf for the Grothendieck topology generated by each coverage separately.
-/
theorem isSheaf_sup (K L : Coverage C) (P : Cᵒᵖ ⥤ Type w) :
    (Presieve.IsSheaf ((K ⊔ L).toGrothendieck C)) P ↔
    (Presieve.IsSheaf (K.toGrothendieck C)) P ∧ (Presieve.IsSheaf (L.toGrothendieck C)) P := by
  refine ⟨fun h ↦ ⟨Presieve.isSheaf_of_le _ ((gi C).gc.monotone_l le_sup_left) h,
      Presieve.isSheaf_of_le _ ((gi C).gc.monotone_l le_sup_right) h⟩, fun h ↦ ?_⟩
  rw [isSheaf_coverage, isSheaf_coverage] at h
  rw [isSheaf_coverage]
  intro X R hR
  cases' hR with hR hR
  · 

Proof state:
case inl
C : Type u_1
inst✝ : Category.{u_2, u_1} C
K L : Coverage C
P : Cᵒᵖ ⥤ Type w
h : (∀ {X : C}, ∀ R ∈ covering K X, IsSheafFor P R) ∧ ∀ {X : C}, ∀ R ∈ covering L X, IsSheafFor P R
X : C
R : Presieve X
hR : R ∈ covering K X
⊢ IsSheafFor P R

Next tactic:
exact h.1 R hR
/--
A presheaf is a sheaf for the Grothendieck topology generated by a union of coverages iff it is a
sheaf for the Grothendieck topology generated by each coverage separately.
-/
theorem isSheaf_sup (K L : Coverage C) (P : Cᵒᵖ ⥤ Type w) :
    (Presieve.IsSheaf ((K ⊔ L).toGrothendieck C)) P ↔
    (Presieve.IsSheaf (K.toGrothendieck C)) P ∧ (Presieve.IsSheaf (L.toGrothendieck C)) P := by
  refine ⟨fun h ↦ ⟨Presieve.isSheaf_of_le _ ((gi C).gc.monotone_l le_sup_left) h,
      Presieve.isSheaf_of_le _ ((gi C).gc.monotone_l le_sup_right) h⟩, fun h ↦ ?_⟩
  rw [isSheaf_coverage, isSheaf_coverage] at h
  rw [isSheaf_coverage]
  intro X R hR
  cases' hR with hR hR
  · exact h.1 R hR
  · 

Proof state:
case inr
C : Type u_1
inst✝ : Category.{u_2, u_1} C
K L : Coverage C
P : Cᵒᵖ ⥤ Type w
h : (∀ {X : C}, ∀ R ∈ covering K X, IsSheafFor P R) ∧ ∀ {X : C}, ∀ R ∈ covering L X, IsSheafFor P R
X : C
R : Presieve X
hR : R ∈ covering L X
⊢ IsSheafFor P R

Next tactic:
exact h.2 R hR
theorem rfind' {f} (hf : Nat.Partrec f) :
    Nat.Partrec
      (Nat.unpaired fun a m =>
        (Nat.rfind fun n => (fun m => m = 0) <$> f (Nat.pair a (n + m))).map (· + m)) :=
  Partrec₂.unpaired'.2 <| by
    

Proof state:
f : ℕ →. ℕ
hf : Partrec f
⊢ Partrec₂ fun a m =>
    Part.map (fun x => x + m) (Nat.rfind fun n => (fun m => decide (m = 0)) <$> f (Nat.pair a (n + m)))

Next tactic:
refine'
      Partrec.map
        ((@Partrec₂.unpaired' fun a b : ℕ =>
              Nat.rfind fun n => (fun m => m = 0) <$> f (Nat.pair a (n + b))).1
          _)
        (Primrec.nat_add.comp Primrec.snd <| Primrec.snd.comp Primrec.fst).to_comp.to₂
theorem rfind' {f} (hf : Nat.Partrec f) :
    Nat.Partrec
      (Nat.unpaired fun a m =>
        (Nat.rfind fun n => (fun m => m = 0) <$> f (Nat.pair a (n + m))).map (· + m)) :=
  Partrec₂.unpaired'.2 <| by
    refine'
      Partrec.map
        ((@Partrec₂.unpaired' fun a b : ℕ =>
              Nat.rfind fun n => (fun m => m = 0) <$> f (Nat.pair a (n + b))).1
          _)
        (Primrec.nat_add.comp Primrec.snd <| Primrec.snd.comp Primrec.fst).to_comp.to₂
    

Proof state:
f : ℕ →. ℕ
hf : Partrec f
⊢ Partrec (unpaired fun a b => Nat.rfind fun n => (fun m => decide (m = 0)) <$> f (Nat.pair a (n + b)))

Next tactic:
have : Nat.Partrec (fun a => Nat.rfind (fun n => (fun m => decide (m = 0)) <$>
      Nat.unpaired (fun a b => f (Nat.pair (Nat.unpair a).1 (b + (Nat.unpair a).2)))
        (Nat.pair a n))) :=
      rfind
        (Partrec₂.unpaired'.2
          ((Partrec.nat_iff.2 hf).comp
              (Primrec₂.pair.comp (Primrec.fst.comp <| Primrec.unpair.comp Primrec.fst)
                  (Primrec.nat_add.comp Primrec.snd
                    (Primrec.snd.comp <| Primrec.unpair.comp Primrec.fst))).to_comp))
theorem rfind' {f} (hf : Nat.Partrec f) :
    Nat.Partrec
      (Nat.unpaired fun a m =>
        (Nat.rfind fun n => (fun m => m = 0) <$> f (Nat.pair a (n + m))).map (· + m)) :=
  Partrec₂.unpaired'.2 <| by
    refine'
      Partrec.map
        ((@Partrec₂.unpaired' fun a b : ℕ =>
              Nat.rfind fun n => (fun m => m = 0) <$> f (Nat.pair a (n + b))).1
          _)
        (Primrec.nat_add.comp Primrec.snd <| Primrec.snd.comp Primrec.fst).to_comp.to₂
    have : Nat.Partrec (fun a => Nat.rfind (fun n => (fun m => decide (m = 0)) <$>
      Nat.unpaired (fun a b => f (Nat.pair (Nat.unpair a).1 (b + (Nat.unpair a).2)))
        (Nat.pair a n))) :=
      rfind
        (Partrec₂.unpaired'.2
          ((Partrec.nat_iff.2 hf).comp
              (Primrec₂.pair.comp (Primrec.fst.comp <| Primrec.unpair.comp Primrec.fst)
                  (Primrec.nat_add.comp Primrec.snd
                    (Primrec.snd.comp <| Primrec.unpair.comp Primrec.fst))).to_comp))
    

Proof state:
f : ℕ →. ℕ
hf : Partrec f
this :
  Partrec fun a =>
    Nat.rfind fun n =>
      (fun m => decide (m = 0)) <$> unpaired (fun a b => f (Nat.pair (unpair a).1 (b + (unpair a).2))) (Nat.pair a n)
⊢ Partrec (unpaired fun a b => Nat.rfind fun n => (fun m => decide (m = 0)) <$> f (Nat.pair a (n + b)))

Next tactic:
simp at this
theorem rfind' {f} (hf : Nat.Partrec f) :
    Nat.Partrec
      (Nat.unpaired fun a m =>
        (Nat.rfind fun n => (fun m => m = 0) <$> f (Nat.pair a (n + m))).map (· + m)) :=
  Partrec₂.unpaired'.2 <| by
    refine'
      Partrec.map
        ((@Partrec₂.unpaired' fun a b : ℕ =>
              Nat.rfind fun n => (fun m => m = 0) <$> f (Nat.pair a (n + b))).1
          _)
        (Primrec.nat_add.comp Primrec.snd <| Primrec.snd.comp Primrec.fst).to_comp.to₂
    have : Nat.Partrec (fun a => Nat.rfind (fun n => (fun m => decide (m = 0)) <$>
      Nat.unpaired (fun a b => f (Nat.pair (Nat.unpair a).1 (b + (Nat.unpair a).2)))
        (Nat.pair a n))) :=
      rfind
        (Partrec₂.unpaired'.2
          ((Partrec.nat_iff.2 hf).comp
              (Primrec₂.pair.comp (Primrec.fst.comp <| Primrec.unpair.comp Primrec.fst)
                  (Primrec.nat_add.comp Primrec.snd
                    (Primrec.snd.comp <| Primrec.unpair.comp Primrec.fst))).to_comp))
    simp at this; 

Proof state:
f : ℕ →. ℕ
hf : Partrec f
this :
  Partrec fun a => Nat.rfind fun n => Part.map (fun m => decide (m = 0)) (f (Nat.pair (unpair a).1 (n + (unpair a).2)))
⊢ Partrec (unpaired fun a b => Nat.rfind fun n => (fun m => decide (m = 0)) <$> f (Nat.pair a (n + b)))

Next tactic:
exact this
theorem const_inj : ∀ {n₁ n₂}, Nat.Partrec.Code.const n₁ = Nat.Partrec.Code.const n₂ → n₁ = n₂
  | 0, 0, _ => by 

Proof state:
x✝ : Code.const 0 = Code.const 0
⊢ 0 = 0

Next tactic:
simp
theorem const_inj : ∀ {n₁ n₂}, Nat.Partrec.Code.const n₁ = Nat.Partrec.Code.const n₂ → n₁ = n₂
  | 0, 0, _ => by simp
  | n₁ + 1, n₂ + 1, h => by
    

Proof state:
n₁ n₂ : ℕ
h : Code.const (n₁ + 1) = Code.const (n₂ + 1)
⊢ n₁ + 1 = n₂ + 1

Next tactic:
dsimp [Nat.add_one, Nat.Partrec.Code.const] at h
theorem const_inj : ∀ {n₁ n₂}, Nat.Partrec.Code.const n₁ = Nat.Partrec.Code.const n₂ → n₁ = n₂
  | 0, 0, _ => by simp
  | n₁ + 1, n₂ + 1, h => by
    dsimp [Nat.add_one, Nat.Partrec.Code.const] at h
    

Proof state:
n₁ n₂ : ℕ
h : comp succ (Code.const n₁) = comp succ (Code.const n₂)
⊢ n₁ + 1 = n₂ + 1

Next tactic:
injection h with h₁ h₂
theorem const_inj : ∀ {n₁ n₂}, Nat.Partrec.Code.const n₁ = Nat.Partrec.Code.const n₂ → n₁ = n₂
  | 0, 0, _ => by simp
  | n₁ + 1, n₂ + 1, h => by
    dsimp [Nat.add_one, Nat.Partrec.Code.const] at h
    injection h with h₁ h₂
    

Proof state:
n₁ n₂ : ℕ
h₁ : succ = succ
h₂ : Code.const n₁ = Code.const n₂
⊢ n₁ + 1 = n₂ + 1

Next tactic:
simp only [const_inj h₂]
/--
A decoder for `Nat.Partrec.Code.encodeCode`, taking any ℕ to the `Nat.Partrec.Code` it represents.
-/
def ofNatCode : ℕ → Code
  | 0 => zero
  | 1 => succ
  | 2 => left
  | 3 => right
  | n + 4 =>
    let m := n.div2.div2
    have hm : m < n + 4 := by
      

Proof state:
n : ℕ
m : ℕ := div2 (div2 n)
⊢ m < n + 4

Next tactic:
simp only [div2_val]
/--
A decoder for `Nat.Partrec.Code.encodeCode`, taking any ℕ to the `Nat.Partrec.Code` it represents.
-/
def ofNatCode : ℕ → Code
  | 0 => zero
  | 1 => succ
  | 2 => left
  | 3 => right
  | n + 4 =>
    let m := n.div2.div2
    have hm : m < n + 4 := by
      simp only [div2_val]
      

Proof state:
n : ℕ
m : ℕ := div2 (div2 n)
⊢ n / 2 / 2 < n + 4

Next tactic:
exact
        lt_of_le_of_lt (le_trans (Nat.div_le_self _ _) (Nat.div_le_self _ _))
          (Nat.succ_le_succ (Nat.le_add_right _ _))
/-- Proof that `Nat.Partrec.Code.ofNatCode` is the inverse of `Nat.Partrec.Code.encodeCode`-/
private theorem encode_ofNatCode : ∀ n, encodeCode (ofNatCode n) = n
  | 0 => by 

Proof state:
⊢ encodeCode (ofNatCode 0) = 0

Next tactic:
simp [ofNatCode, encodeCode]
/-- Proof that `Nat.Partrec.Code.ofNatCode` is the inverse of `Nat.Partrec.Code.encodeCode`-/
private theorem encode_ofNatCode : ∀ n, encodeCode (ofNatCode n) = n
  | 0 => by simp [ofNatCode, encodeCode]
  | 1 => by 

Proof state:
⊢ encodeCode (ofNatCode 1) = 1

Next tactic:
simp [ofNatCode, encodeCode]
/-- Proof that `Nat.Partrec.Code.ofNatCode` is the inverse of `Nat.Partrec.Code.encodeCode`-/
private theorem encode_ofNatCode : ∀ n, encodeCode (ofNatCode n) = n
  | 0 => by simp [ofNatCode, encodeCode]
  | 1 => by simp [ofNatCode, encodeCode]
  | 2 => by 

Proof state:
⊢ encodeCode (ofNatCode 2) = 2

Next tactic:
simp [ofNatCode, encodeCode]
/-- Proof that `Nat.Partrec.Code.ofNatCode` is the inverse of `Nat.Partrec.Code.encodeCode`-/
private theorem encode_ofNatCode : ∀ n, encodeCode (ofNatCode n) = n
  | 0 => by simp [ofNatCode, encodeCode]
  | 1 => by simp [ofNatCode, encodeCode]
  | 2 => by simp [ofNatCode, encodeCode]
  | 3 => by 

Proof state:
⊢ encodeCode (ofNatCode 3) = 3

Next tactic:
simp [ofNatCode, encodeCode]
/-- Proof that `Nat.Partrec.Code.ofNatCode` is the inverse of `Nat.Partrec.Code.encodeCode`-/
private theorem encode_ofNatCode : ∀ n, encodeCode (ofNatCode n) = n
  | 0 => by simp [ofNatCode, encodeCode]
  | 1 => by simp [ofNatCode, encodeCode]
  | 2 => by simp [ofNatCode, encodeCode]
  | 3 => by simp [ofNatCode, encodeCode]
  | n + 4 => by
    

Proof state:
n : ℕ
⊢ encodeCode (ofNatCode (n + 4)) = n + 4

Next tactic:
let m := n.div2.div2
/-- Proof that `Nat.Partrec.Code.ofNatCode` is the inverse of `Nat.Partrec.Code.encodeCode`-/
private theorem encode_ofNatCode : ∀ n, encodeCode (ofNatCode n) = n
  | 0 => by simp [ofNatCode, encodeCode]
  | 1 => by simp [ofNatCode, encodeCode]
  | 2 => by simp [ofNatCode, encodeCode]
  | 3 => by simp [ofNatCode, encodeCode]
  | n + 4 => by
    let m := n.div2.div2
    

Proof state:
n : ℕ
m : ℕ := div2 (div2 n)
⊢ encodeCode (ofNatCode (n + 4)) = n + 4

Next tactic:
have hm : m < n + 4 := by
      simp only [div2_val]
      exact
        lt_of_le_of_lt (le_trans (Nat.div_le_self _ _) (Nat.div_le_self _ _))
          (Nat.succ_le_succ (Nat.le_add_right _ _))
/-- Proof that `Nat.Partrec.Code.ofNatCode` is the inverse of `Nat.Partrec.Code.encodeCode`-/
private theorem encode_ofNatCode : ∀ n, encodeCode (ofNatCode n) = n
  | 0 => by simp [ofNatCode, encodeCode]
  | 1 => by simp [ofNatCode, encodeCode]
  | 2 => by simp [ofNatCode, encodeCode]
  | 3 => by simp [ofNatCode, encodeCode]
  | n + 4 => by
    let m := n.div2.div2
    have hm : m < n + 4 := by
      

Proof state:
n : ℕ
m : ℕ := div2 (div2 n)
⊢ m < n + 4

Next tactic:
simp only [div2_val]
/-- Proof that `Nat.Partrec.Code.ofNatCode` is the inverse of `Nat.Partrec.Code.encodeCode`-/
private theorem encode_ofNatCode : ∀ n, encodeCode (ofNatCode n) = n
  | 0 => by simp [ofNatCode, encodeCode]
  | 1 => by simp [ofNatCode, encodeCode]
  | 2 => by simp [ofNatCode, encodeCode]
  | 3 => by simp [ofNatCode, encodeCode]
  | n + 4 => by
    let m := n.div2.div2
    have hm : m < n + 4 := by
      simp only [div2_val]
      

Proof state:
n : ℕ
m : ℕ := div2 (div2 n)
⊢ n / 2 / 2 < n + 4

Next tactic:
exact
        lt_of_le_of_lt (le_trans (Nat.div_le_self _ _) (Nat.div_le_self _ _))
          (Nat.succ_le_succ (Nat.le_add_right _ _))
/-- Proof that `Nat.Partrec.Code.ofNatCode` is the inverse of `Nat.Partrec.Code.encodeCode`-/
private theorem encode_ofNatCode : ∀ n, encodeCode (ofNatCode n) = n
  | 0 => by simp [ofNatCode, encodeCode]
  | 1 => by simp [ofNatCode, encodeCode]
  | 2 => by simp [ofNatCode, encodeCode]
  | 3 => by simp [ofNatCode, encodeCode]
  | n + 4 => by
    let m := n.div2.div2
    have hm : m < n + 4 := by
      simp only [div2_val]
      exact
        lt_of_le_of_lt (le_trans (Nat.div_le_self _ _) (Nat.div_le_self _ _))
          (Nat.succ_le_succ (Nat.le_add_right _ _))
    

Proof state:
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
⊢ encodeCode (ofNatCode (n + 4)) = n + 4

Next tactic:
have _m1 : m.unpair.1 < n + 4 := lt_of_le_of_lt m.unpair_left_le hm
/-- Proof that `Nat.Partrec.Code.ofNatCode` is the inverse of `Nat.Partrec.Code.encodeCode`-/
private theorem encode_ofNatCode : ∀ n, encodeCode (ofNatCode n) = n
  | 0 => by simp [ofNatCode, encodeCode]
  | 1 => by simp [ofNatCode, encodeCode]
  | 2 => by simp [ofNatCode, encodeCode]
  | 3 => by simp [ofNatCode, encodeCode]
  | n + 4 => by
    let m := n.div2.div2
    have hm : m < n + 4 := by
      simp only [div2_val]
      exact
        lt_of_le_of_lt (le_trans (Nat.div_le_self _ _) (Nat.div_le_self _ _))
          (Nat.succ_le_succ (Nat.le_add_right _ _))
    have _m1 : m.unpair.1 < n + 4 := lt_of_le_of_lt m.unpair_left_le hm
    

Proof state:
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
_m1 : (unpair m).1 < n + 4
⊢ encodeCode (ofNatCode (n + 4)) = n + 4

Next tactic:
have _m2 : m.unpair.2 < n + 4 := lt_of_le_of_lt m.unpair_right_le hm
/-- Proof that `Nat.Partrec.Code.ofNatCode` is the inverse of `Nat.Partrec.Code.encodeCode`-/
private theorem encode_ofNatCode : ∀ n, encodeCode (ofNatCode n) = n
  | 0 => by simp [ofNatCode, encodeCode]
  | 1 => by simp [ofNatCode, encodeCode]
  | 2 => by simp [ofNatCode, encodeCode]
  | 3 => by simp [ofNatCode, encodeCode]
  | n + 4 => by
    let m := n.div2.div2
    have hm : m < n + 4 := by
      simp only [div2_val]
      exact
        lt_of_le_of_lt (le_trans (Nat.div_le_self _ _) (Nat.div_le_self _ _))
          (Nat.succ_le_succ (Nat.le_add_right _ _))
    have _m1 : m.unpair.1 < n + 4 := lt_of_le_of_lt m.unpair_left_le hm
    have _m2 : m.unpair.2 < n + 4 := lt_of_le_of_lt m.unpair_right_le hm
    

Proof state:
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
_m1 : (unpair m).1 < n + 4
_m2 : (unpair m).2 < n + 4
⊢ encodeCode (ofNatCode (n + 4)) = n + 4

Next tactic:
have IH := encode_ofNatCode m
/-- Proof that `Nat.Partrec.Code.ofNatCode` is the inverse of `Nat.Partrec.Code.encodeCode`-/
private theorem encode_ofNatCode : ∀ n, encodeCode (ofNatCode n) = n
  | 0 => by simp [ofNatCode, encodeCode]
  | 1 => by simp [ofNatCode, encodeCode]
  | 2 => by simp [ofNatCode, encodeCode]
  | 3 => by simp [ofNatCode, encodeCode]
  | n + 4 => by
    let m := n.div2.div2
    have hm : m < n + 4 := by
      simp only [div2_val]
      exact
        lt_of_le_of_lt (le_trans (Nat.div_le_self _ _) (Nat.div_le_self _ _))
          (Nat.succ_le_succ (Nat.le_add_right _ _))
    have _m1 : m.unpair.1 < n + 4 := lt_of_le_of_lt m.unpair_left_le hm
    have _m2 : m.unpair.2 < n + 4 := lt_of_le_of_lt m.unpair_right_le hm
    have IH := encode_ofNatCode m
    

Proof state:
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
_m1 : (unpair m).1 < n + 4
_m2 : (unpair m).2 < n + 4
IH : encodeCode (ofNatCode m) = m
⊢ encodeCode (ofNatCode (n + 4)) = n + 4

Next tactic:
have IH1 := encode_ofNatCode m.unpair.1
/-- Proof that `Nat.Partrec.Code.ofNatCode` is the inverse of `Nat.Partrec.Code.encodeCode`-/
private theorem encode_ofNatCode : ∀ n, encodeCode (ofNatCode n) = n
  | 0 => by simp [ofNatCode, encodeCode]
  | 1 => by simp [ofNatCode, encodeCode]
  | 2 => by simp [ofNatCode, encodeCode]
  | 3 => by simp [ofNatCode, encodeCode]
  | n + 4 => by
    let m := n.div2.div2
    have hm : m < n + 4 := by
      simp only [div2_val]
      exact
        lt_of_le_of_lt (le_trans (Nat.div_le_self _ _) (Nat.div_le_self _ _))
          (Nat.succ_le_succ (Nat.le_add_right _ _))
    have _m1 : m.unpair.1 < n + 4 := lt_of_le_of_lt m.unpair_left_le hm
    have _m2 : m.unpair.2 < n + 4 := lt_of_le_of_lt m.unpair_right_le hm
    have IH := encode_ofNatCode m
    have IH1 := encode_ofNatCode m.unpair.1
    

Proof state:
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
_m1 : (unpair m).1 < n + 4
_m2 : (unpair m).2 < n + 4
IH : encodeCode (ofNatCode m) = m
IH1 : encodeCode (ofNatCode (unpair m).1) = (unpair m).1
⊢ encodeCode (ofNatCode (n + 4)) = n + 4

Next tactic:
have IH2 := encode_ofNatCode m.unpair.2
/-- Proof that `Nat.Partrec.Code.ofNatCode` is the inverse of `Nat.Partrec.Code.encodeCode`-/
private theorem encode_ofNatCode : ∀ n, encodeCode (ofNatCode n) = n
  | 0 => by simp [ofNatCode, encodeCode]
  | 1 => by simp [ofNatCode, encodeCode]
  | 2 => by simp [ofNatCode, encodeCode]
  | 3 => by simp [ofNatCode, encodeCode]
  | n + 4 => by
    let m := n.div2.div2
    have hm : m < n + 4 := by
      simp only [div2_val]
      exact
        lt_of_le_of_lt (le_trans (Nat.div_le_self _ _) (Nat.div_le_self _ _))
          (Nat.succ_le_succ (Nat.le_add_right _ _))
    have _m1 : m.unpair.1 < n + 4 := lt_of_le_of_lt m.unpair_left_le hm
    have _m2 : m.unpair.2 < n + 4 := lt_of_le_of_lt m.unpair_right_le hm
    have IH := encode_ofNatCode m
    have IH1 := encode_ofNatCode m.unpair.1
    have IH2 := encode_ofNatCode m.unpair.2
    

Proof state:
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
_m1 : (unpair m).1 < n + 4
_m2 : (unpair m).2 < n + 4
IH : encodeCode (ofNatCode m) = m
IH1 : encodeCode (ofNatCode (unpair m).1) = (unpair m).1
IH2 : encodeCode (ofNatCode (unpair m).2) = (unpair m).2
⊢ encodeCode (ofNatCode (n + 4)) = n + 4

Next tactic:
conv_rhs => rw [← Nat.bit_decomp n, ← Nat.bit_decomp n.div2]
/-- Proof that `Nat.Partrec.Code.ofNatCode` is the inverse of `Nat.Partrec.Code.encodeCode`-/
private theorem encode_ofNatCode : ∀ n, encodeCode (ofNatCode n) = n
  | 0 => by simp [ofNatCode, encodeCode]
  | 1 => by simp [ofNatCode, encodeCode]
  | 2 => by simp [ofNatCode, encodeCode]
  | 3 => by simp [ofNatCode, encodeCode]
  | n + 4 => by
    let m := n.div2.div2
    have hm : m < n + 4 := by
      simp only [div2_val]
      exact
        lt_of_le_of_lt (le_trans (Nat.div_le_self _ _) (Nat.div_le_self _ _))
          (Nat.succ_le_succ (Nat.le_add_right _ _))
    have _m1 : m.unpair.1 < n + 4 := lt_of_le_of_lt m.unpair_left_le hm
    have _m2 : m.unpair.2 < n + 4 := lt_of_le_of_lt m.unpair_right_le hm
    have IH := encode_ofNatCode m
    have IH1 := encode_ofNatCode m.unpair.1
    have IH2 := encode_ofNatCode m.unpair.2
    conv_rhs => 

Proof state:
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
_m1 : (unpair m).1 < n + 4
_m2 : (unpair m).2 < n + 4
IH : encodeCode (ofNatCode m) = m
IH1 : encodeCode (ofNatCode (unpair m).1) = (unpair m).1
IH2 : encodeCode (ofNatCode (unpair m).2) = (unpair m).2
| n + 4

Next tactic:
rw [← Nat.bit_decomp n, ← Nat.bit_decomp n.div2]
/-- Proof that `Nat.Partrec.Code.ofNatCode` is the inverse of `Nat.Partrec.Code.encodeCode`-/
private theorem encode_ofNatCode : ∀ n, encodeCode (ofNatCode n) = n
  | 0 => by simp [ofNatCode, encodeCode]
  | 1 => by simp [ofNatCode, encodeCode]
  | 2 => by simp [ofNatCode, encodeCode]
  | 3 => by simp [ofNatCode, encodeCode]
  | n + 4 => by
    let m := n.div2.div2
    have hm : m < n + 4 := by
      simp only [div2_val]
      exact
        lt_of_le_of_lt (le_trans (Nat.div_le_self _ _) (Nat.div_le_self _ _))
          (Nat.succ_le_succ (Nat.le_add_right _ _))
    have _m1 : m.unpair.1 < n + 4 := lt_of_le_of_lt m.unpair_left_le hm
    have _m2 : m.unpair.2 < n + 4 := lt_of_le_of_lt m.unpair_right_le hm
    have IH := encode_ofNatCode m
    have IH1 := encode_ofNatCode m.unpair.1
    have IH2 := encode_ofNatCode m.unpair.2
    conv_rhs => rw [← Nat.bit_decomp n, ← Nat.bit_decomp n.div2]
    

Proof state:
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
_m1 : (unpair m).1 < n + 4
_m2 : (unpair m).2 < n + 4
IH : encodeCode (ofNatCode m) = m
IH1 : encodeCode (ofNatCode (unpair m).1) = (unpair m).1
IH2 : encodeCode (ofNatCode (unpair m).2) = (unpair m).2
⊢ encodeCode (ofNatCode (n + 4)) = bit (bodd n) (bit (bodd (div2 n)) (div2 (div2 n))) + 4

Next tactic:
simp only [ofNatCode._eq_5]
/-- Proof that `Nat.Partrec.Code.ofNatCode` is the inverse of `Nat.Partrec.Code.encodeCode`-/
private theorem encode_ofNatCode : ∀ n, encodeCode (ofNatCode n) = n
  | 0 => by simp [ofNatCode, encodeCode]
  | 1 => by simp [ofNatCode, encodeCode]
  | 2 => by simp [ofNatCode, encodeCode]
  | 3 => by simp [ofNatCode, encodeCode]
  | n + 4 => by
    let m := n.div2.div2
    have hm : m < n + 4 := by
      simp only [div2_val]
      exact
        lt_of_le_of_lt (le_trans (Nat.div_le_self _ _) (Nat.div_le_self _ _))
          (Nat.succ_le_succ (Nat.le_add_right _ _))
    have _m1 : m.unpair.1 < n + 4 := lt_of_le_of_lt m.unpair_left_le hm
    have _m2 : m.unpair.2 < n + 4 := lt_of_le_of_lt m.unpair_right_le hm
    have IH := encode_ofNatCode m
    have IH1 := encode_ofNatCode m.unpair.1
    have IH2 := encode_ofNatCode m.unpair.2
    conv_rhs => rw [← Nat.bit_decomp n, ← Nat.bit_decomp n.div2]
    simp only [ofNatCode._eq_5]
    

Proof state:
n : ℕ
m : ℕ := div2 (div2 n)
hm : m < n + 4
_m1 : (unpair m).1 < n + 4
_m2 : (unpair m).2 < n + 4
IH : encodeCode (ofNatCode m) = m
IH1 : encodeCode (ofNatCode (unpair m).1) = (unpair m).1
IH2 : encodeCode (ofNatCode (unpair m).2) = (unpair m).2
⊢ encodeCode
      (match bodd n, bodd (div2 n) with
      | false, false => pair (ofNatCode (unpair (div2 (div2 n))).1) (ofNatCode (unpair (div2 (div2 n))).2)
      | false, true => comp (ofNatCode (unpair (div2 (div2 n))).1) (ofNatCode (unpair (div2 (div2 n))).2)
      | true, false => prec (ofNatCode (unpair (div2 (div2 n))).1) (ofNatCode (unpair (div2 (div2 n))).2)
      | true, true => rfind' (ofNatCode (div2 (div2 n)))) =
    bit (bodd n) (bit (bodd (div2 n)) (div2 (div2 n))) + 4

Next tactic:
cases n.bodd