l3lab/ntp-mathlib huggingface dataset:
/-- If the order has a bot but no top, `toZ` defines an `OrderIso` between `ι` and `ℕ`. -/
def orderIsoNatOfLinearSuccPredArch [NoMaxOrder ι] [OrderBot ι] : ι ≃o ℕ where
  toFun i := (toZ ⊥ i).toNat
  invFun n := succ^[n] ⊥
  left_inv i := by
    dsimp only
    exact iterate_succ_toZ i bot_le
  right_inv n := by
    dsimp only
    rw [toZ_iterate_succ]
    exact Int.toNat_coe_nat n
  map_rel_iff' := by
    intro i j
    

Proof state:
ι : Type u_1
inst✝⁵ : LinearOrder ι
inst✝⁴ : SuccOrder ι
inst✝³ : PredOrder ι
inst✝² : IsSuccArchimedean ι
inst✝¹ : NoMaxOrder ι
inst✝ : OrderBot ι
i j : ι
⊢ { toFun := fun i => Int.toNat (toZ ⊥ i), invFun := fun n => succ^[n] ⊥,
          left_inv := (_ : ∀ (i : ι), (fun n => succ^[n] ⊥) ((fun i => Int.toNat (toZ ⊥ i)) i) = i),
          right_inv := (_ : ∀ (n : ℕ), (fun i => Int.toNat (toZ ⊥ i)) ((fun n => succ^[n] ⊥) n) = n) }
        i ≤
      { toFun := fun i => Int.toNat (toZ ⊥ i), invFun := fun n => succ^[n] ⊥,
          left_inv := (_ : ∀ (i : ι), (fun n => succ^[n] ⊥) ((fun i => Int.toNat (toZ ⊥ i)) i) = i),
          right_inv := (_ : ∀ (n : ℕ), (fun i => Int.toNat (toZ ⊥ i)) ((fun n => succ^[n] ⊥) n) = n) }
        j ↔
    i ≤ j

Next tactic:
simp only [Equiv.coe_fn_mk, Int.toNat_le]
/-- If the order has a bot but no top, `toZ` defines an `OrderIso` between `ι` and `ℕ`. -/
def orderIsoNatOfLinearSuccPredArch [NoMaxOrder ι] [OrderBot ι] : ι ≃o ℕ where
  toFun i := (toZ ⊥ i).toNat
  invFun n := succ^[n] ⊥
  left_inv i := by
    dsimp only
    exact iterate_succ_toZ i bot_le
  right_inv n := by
    dsimp only
    rw [toZ_iterate_succ]
    exact Int.toNat_coe_nat n
  map_rel_iff' := by
    intro i j
    simp only [Equiv.coe_fn_mk, Int.toNat_le]
    

Proof state:
ι : Type u_1
inst✝⁵ : LinearOrder ι
inst✝⁴ : SuccOrder ι
inst✝³ : PredOrder ι
inst✝² : IsSuccArchimedean ι
inst✝¹ : NoMaxOrder ι
inst✝ : OrderBot ι
i j : ι
⊢ toZ ⊥ i ≤ ↑(Int.toNat (toZ ⊥ j)) ↔ i ≤ j

Next tactic:
rw [← @toZ_le_iff ι _ _ _ _ ⊥, Int.toNat_of_nonneg (toZ_nonneg bot_le)]
/-- If the order has both a bot and a top, `toZ` gives an `OrderIso` between `ι` and
`Finset.range n` for some `n`. -/
def orderIsoRangeOfLinearSuccPredArch [OrderBot ι] [OrderTop ι] :
    ι ≃o Finset.range ((toZ ⊥ (⊤ : ι)).toNat + 1) where
  toFun i :=
    ⟨(toZ ⊥ i).toNat,
      Finset.mem_range_succ_iff.mpr (Int.toNat_le_toNat ((toZ_le_iff _ _).mpr le_top))⟩
  invFun n := succ^[n] ⊥
  left_inv i := iterate_succ_toZ i bot_le
  right_inv n := by
    

Proof state:
ι : Type u_1
inst✝⁵ : LinearOrder ι
inst✝⁴ : SuccOrder ι
inst✝³ : PredOrder ι
inst✝² : IsSuccArchimedean ι
inst✝¹ : OrderBot ι
inst✝ : OrderTop ι
n : { x // x ∈ Finset.range (Int.toNat (toZ ⊥ ⊤) + 1) }
⊢ (fun i =>
        { val := Int.toNat (toZ ⊥ i),
          property := (_ : Int.toNat (toZ ⊥ i) ∈ Finset.range (Nat.succ (Int.toNat (toZ ⊥ ⊤)))) })
      ((fun n => succ^[↑n] ⊥) n) =
    n

Next tactic:
ext1
/-- If the order has both a bot and a top, `toZ` gives an `OrderIso` between `ι` and
`Finset.range n` for some `n`. -/
def orderIsoRangeOfLinearSuccPredArch [OrderBot ι] [OrderTop ι] :
    ι ≃o Finset.range ((toZ ⊥ (⊤ : ι)).toNat + 1) where
  toFun i :=
    ⟨(toZ ⊥ i).toNat,
      Finset.mem_range_succ_iff.mpr (Int.toNat_le_toNat ((toZ_le_iff _ _).mpr le_top))⟩
  invFun n := succ^[n] ⊥
  left_inv i := iterate_succ_toZ i bot_le
  right_inv n := by
    ext1
    

Proof state:
case a
ι : Type u_1
inst✝⁵ : LinearOrder ι
inst✝⁴ : SuccOrder ι
inst✝³ : PredOrder ι
inst✝² : IsSuccArchimedean ι
inst✝¹ : OrderBot ι
inst✝ : OrderTop ι
n : { x // x ∈ Finset.range (Int.toNat (toZ ⊥ ⊤) + 1) }
⊢ ↑((fun i =>
          { val := Int.toNat (toZ ⊥ i),
            property := (_ : Int.toNat (toZ ⊥ i) ∈ Finset.range (Nat.succ (Int.toNat (toZ ⊥ ⊤)))) })
        ((fun n => succ^[↑n] ⊥) n)) =
    ↑n

Next tactic:
simp only [Subtype.coe_mk]
/-- If the order has both a bot and a top, `toZ` gives an `OrderIso` between `ι` and
`Finset.range n` for some `n`. -/
def orderIsoRangeOfLinearSuccPredArch [OrderBot ι] [OrderTop ι] :
    ι ≃o Finset.range ((toZ ⊥ (⊤ : ι)).toNat + 1) where
  toFun i :=
    ⟨(toZ ⊥ i).toNat,
      Finset.mem_range_succ_iff.mpr (Int.toNat_le_toNat ((toZ_le_iff _ _).mpr le_top))⟩
  invFun n := succ^[n] ⊥
  left_inv i := iterate_succ_toZ i bot_le
  right_inv n := by
    ext1
    simp only [Subtype.coe_mk]
    

Proof state:
case a
ι : Type u_1
inst✝⁵ : LinearOrder ι
inst✝⁴ : SuccOrder ι
inst✝³ : PredOrder ι
inst✝² : IsSuccArchimedean ι
inst✝¹ : OrderBot ι
inst✝ : OrderTop ι
n : { x // x ∈ Finset.range (Int.toNat (toZ ⊥ ⊤) + 1) }
⊢ Int.toNat (toZ ⊥ (succ^[↑n] ⊥)) = ↑n

Next tactic:
refine' le_antisymm _ _
/-- If the order has both a bot and a top, `toZ` gives an `OrderIso` between `ι` and
`Finset.range n` for some `n`. -/
def orderIsoRangeOfLinearSuccPredArch [OrderBot ι] [OrderTop ι] :
    ι ≃o Finset.range ((toZ ⊥ (⊤ : ι)).toNat + 1) where
  toFun i :=
    ⟨(toZ ⊥ i).toNat,
      Finset.mem_range_succ_iff.mpr (Int.toNat_le_toNat ((toZ_le_iff _ _).mpr le_top))⟩
  invFun n := succ^[n] ⊥
  left_inv i := iterate_succ_toZ i bot_le
  right_inv n := by
    ext1
    simp only [Subtype.coe_mk]
    refine' le_antisymm _ _
    · 

Proof state:
case a.refine'_1
ι : Type u_1
inst✝⁵ : LinearOrder ι
inst✝⁴ : SuccOrder ι
inst✝³ : PredOrder ι
inst✝² : IsSuccArchimedean ι
inst✝¹ : OrderBot ι
inst✝ : OrderTop ι
n : { x // x ∈ Finset.range (Int.toNat (toZ ⊥ ⊤) + 1) }
⊢ Int.toNat (toZ ⊥ (succ^[↑n] ⊥)) ≤ ↑n

Next tactic:
rw [Int.toNat_le]
/-- If the order has both a bot and a top, `toZ` gives an `OrderIso` between `ι` and
`Finset.range n` for some `n`. -/
def orderIsoRangeOfLinearSuccPredArch [OrderBot ι] [OrderTop ι] :
    ι ≃o Finset.range ((toZ ⊥ (⊤ : ι)).toNat + 1) where
  toFun i :=
    ⟨(toZ ⊥ i).toNat,
      Finset.mem_range_succ_iff.mpr (Int.toNat_le_toNat ((toZ_le_iff _ _).mpr le_top))⟩
  invFun n := succ^[n] ⊥
  left_inv i := iterate_succ_toZ i bot_le
  right_inv n := by
    ext1
    simp only [Subtype.coe_mk]
    refine' le_antisymm _ _
    · rw [Int.toNat_le]
      

Proof state:
case a.refine'_1
ι : Type u_1
inst✝⁵ : LinearOrder ι
inst✝⁴ : SuccOrder ι
inst✝³ : PredOrder ι
inst✝² : IsSuccArchimedean ι
inst✝¹ : OrderBot ι
inst✝ : OrderTop ι
n : { x // x ∈ Finset.range (Int.toNat (toZ ⊥ ⊤) + 1) }
⊢ toZ ⊥ (succ^[↑n] ⊥) ≤ ↑↑n

Next tactic:
exact toZ_iterate_succ_le _
/-- If the order has both a bot and a top, `toZ` gives an `OrderIso` between `ι` and
`Finset.range n` for some `n`. -/
def orderIsoRangeOfLinearSuccPredArch [OrderBot ι] [OrderTop ι] :
    ι ≃o Finset.range ((toZ ⊥ (⊤ : ι)).toNat + 1) where
  toFun i :=
    ⟨(toZ ⊥ i).toNat,
      Finset.mem_range_succ_iff.mpr (Int.toNat_le_toNat ((toZ_le_iff _ _).mpr le_top))⟩
  invFun n := succ^[n] ⊥
  left_inv i := iterate_succ_toZ i bot_le
  right_inv n := by
    ext1
    simp only [Subtype.coe_mk]
    refine' le_antisymm _ _
    · rw [Int.toNat_le]
      exact toZ_iterate_succ_le _
    

Proof state:
case a.refine'_2
ι : Type u_1
inst✝⁵ : LinearOrder ι
inst✝⁴ : SuccOrder ι
inst✝³ : PredOrder ι
inst✝² : IsSuccArchimedean ι
inst✝¹ : OrderBot ι
inst✝ : OrderTop ι
n : { x // x ∈ Finset.range (Int.toNat (toZ ⊥ ⊤) + 1) }
⊢ ↑n ≤ Int.toNat (toZ ⊥ (succ^[↑n] ⊥))

Next tactic:
by_cases hn_max : IsMax (succ^[↑n] (⊥ : ι))
/-- If the order has both a bot and a top, `toZ` gives an `OrderIso` between `ι` and
`Finset.range n` for some `n`. -/
def orderIsoRangeOfLinearSuccPredArch [OrderBot ι] [OrderTop ι] :
    ι ≃o Finset.range ((toZ ⊥ (⊤ : ι)).toNat + 1) where
  toFun i :=
    ⟨(toZ ⊥ i).toNat,
      Finset.mem_range_succ_iff.mpr (Int.toNat_le_toNat ((toZ_le_iff _ _).mpr le_top))⟩
  invFun n := succ^[n] ⊥
  left_inv i := iterate_succ_toZ i bot_le
  right_inv n := by
    ext1
    simp only [Subtype.coe_mk]
    refine' le_antisymm _ _
    · rw [Int.toNat_le]
      exact toZ_iterate_succ_le _
    by_cases hn_max : IsMax (succ^[↑n] (⊥ : ι))
    · 

Proof state:
case pos
ι : Type u_1
inst✝⁵ : LinearOrder ι
inst✝⁴ : SuccOrder ι
inst✝³ : PredOrder ι
inst✝² : IsSuccArchimedean ι
inst✝¹ : OrderBot ι
inst✝ : OrderTop ι
n : { x // x ∈ Finset.range (Int.toNat (toZ ⊥ ⊤) + 1) }
hn_max : IsMax (succ^[↑n] ⊥)
⊢ ↑n ≤ Int.toNat (toZ ⊥ (succ^[↑n] ⊥))

Next tactic:
rw [← isTop_iff_isMax, isTop_iff_eq_top] at hn_max
/-- If the order has both a bot and a top, `toZ` gives an `OrderIso` between `ι` and
`Finset.range n` for some `n`. -/
def orderIsoRangeOfLinearSuccPredArch [OrderBot ι] [OrderTop ι] :
    ι ≃o Finset.range ((toZ ⊥ (⊤ : ι)).toNat + 1) where
  toFun i :=
    ⟨(toZ ⊥ i).toNat,
      Finset.mem_range_succ_iff.mpr (Int.toNat_le_toNat ((toZ_le_iff _ _).mpr le_top))⟩
  invFun n := succ^[n] ⊥
  left_inv i := iterate_succ_toZ i bot_le
  right_inv n := by
    ext1
    simp only [Subtype.coe_mk]
    refine' le_antisymm _ _
    · rw [Int.toNat_le]
      exact toZ_iterate_succ_le _
    by_cases hn_max : IsMax (succ^[↑n] (⊥ : ι))
    · rw [← isTop_iff_isMax, isTop_iff_eq_top] at hn_max
      

Proof state:
case pos
ι : Type u_1
inst✝⁵ : LinearOrder ι
inst✝⁴ : SuccOrder ι
inst✝³ : PredOrder ι
inst✝² : IsSuccArchimedean ι
inst✝¹ : OrderBot ι
inst✝ : OrderTop ι
n : { x // x ∈ Finset.range (Int.toNat (toZ ⊥ ⊤) + 1) }
hn_max : succ^[↑n] ⊥ = ⊤
⊢ ↑n ≤ Int.toNat (toZ ⊥ (succ^[↑n] ⊥))

Next tactic:
rw [hn_max]
/-- If the order has both a bot and a top, `toZ` gives an `OrderIso` between `ι` and
`Finset.range n` for some `n`. -/
def orderIsoRangeOfLinearSuccPredArch [OrderBot ι] [OrderTop ι] :
    ι ≃o Finset.range ((toZ ⊥ (⊤ : ι)).toNat + 1) where
  toFun i :=
    ⟨(toZ ⊥ i).toNat,
      Finset.mem_range_succ_iff.mpr (Int.toNat_le_toNat ((toZ_le_iff _ _).mpr le_top))⟩
  invFun n := succ^[n] ⊥
  left_inv i := iterate_succ_toZ i bot_le
  right_inv n := by
    ext1
    simp only [Subtype.coe_mk]
    refine' le_antisymm _ _
    · rw [Int.toNat_le]
      exact toZ_iterate_succ_le _
    by_cases hn_max : IsMax (succ^[↑n] (⊥ : ι))
    · rw [← isTop_iff_isMax, isTop_iff_eq_top] at hn_max
      rw [hn_max]
      

Proof state:
case pos
ι : Type u_1
inst✝⁵ : LinearOrder ι
inst✝⁴ : SuccOrder ι
inst✝³ : PredOrder ι
inst✝² : IsSuccArchimedean ι
inst✝¹ : OrderBot ι
inst✝ : OrderTop ι
n : { x // x ∈ Finset.range (Int.toNat (toZ ⊥ ⊤) + 1) }
hn_max : succ^[↑n] ⊥ = ⊤
⊢ ↑n ≤ Int.toNat (toZ ⊥ ⊤)

Next tactic:
exact Nat.lt_succ_iff.mp (Finset.mem_range.mp n.prop)
/-- If the order has both a bot and a top, `toZ` gives an `OrderIso` between `ι` and
`Finset.range n` for some `n`. -/
def orderIsoRangeOfLinearSuccPredArch [OrderBot ι] [OrderTop ι] :
    ι ≃o Finset.range ((toZ ⊥ (⊤ : ι)).toNat + 1) where
  toFun i :=
    ⟨(toZ ⊥ i).toNat,
      Finset.mem_range_succ_iff.mpr (Int.toNat_le_toNat ((toZ_le_iff _ _).mpr le_top))⟩
  invFun n := succ^[n] ⊥
  left_inv i := iterate_succ_toZ i bot_le
  right_inv n := by
    ext1
    simp only [Subtype.coe_mk]
    refine' le_antisymm _ _
    · rw [Int.toNat_le]
      exact toZ_iterate_succ_le _
    by_cases hn_max : IsMax (succ^[↑n] (⊥ : ι))
    · rw [← isTop_iff_isMax, isTop_iff_eq_top] at hn_max
      rw [hn_max]
      exact Nat.lt_succ_iff.mp (Finset.mem_range.mp n.prop)
    · 

Proof state:
case neg
ι : Type u_1
inst✝⁵ : LinearOrder ι
inst✝⁴ : SuccOrder ι
inst✝³ : PredOrder ι
inst✝² : IsSuccArchimedean ι
inst✝¹ : OrderBot ι
inst✝ : OrderTop ι
n : { x // x ∈ Finset.range (Int.toNat (toZ ⊥ ⊤) + 1) }
hn_max : ¬IsMax (succ^[↑n] ⊥)
⊢ ↑n ≤ Int.toNat (toZ ⊥ (succ^[↑n] ⊥))

Next tactic:
rw [toZ_iterate_succ_of_not_isMax _ hn_max]
/-- If the order has both a bot and a top, `toZ` gives an `OrderIso` between `ι` and
`Finset.range n` for some `n`. -/
def orderIsoRangeOfLinearSuccPredArch [OrderBot ι] [OrderTop ι] :
    ι ≃o Finset.range ((toZ ⊥ (⊤ : ι)).toNat + 1) where
  toFun i :=
    ⟨(toZ ⊥ i).toNat,
      Finset.mem_range_succ_iff.mpr (Int.toNat_le_toNat ((toZ_le_iff _ _).mpr le_top))⟩
  invFun n := succ^[n] ⊥
  left_inv i := iterate_succ_toZ i bot_le
  right_inv n := by
    ext1
    simp only [Subtype.coe_mk]
    refine' le_antisymm _ _
    · rw [Int.toNat_le]
      exact toZ_iterate_succ_le _
    by_cases hn_max : IsMax (succ^[↑n] (⊥ : ι))
    · rw [← isTop_iff_isMax, isTop_iff_eq_top] at hn_max
      rw [hn_max]
      exact Nat.lt_succ_iff.mp (Finset.mem_range.mp n.prop)
    · rw [toZ_iterate_succ_of_not_isMax _ hn_max]
      

Proof state:
case neg
ι : Type u_1
inst✝⁵ : LinearOrder ι
inst✝⁴ : SuccOrder ι
inst✝³ : PredOrder ι
inst✝² : IsSuccArchimedean ι
inst✝¹ : OrderBot ι
inst✝ : OrderTop ι
n : { x // x ∈ Finset.range (Int.toNat (toZ ⊥ ⊤) + 1) }
hn_max : ¬IsMax (succ^[↑n] ⊥)
⊢ ↑n ≤ Int.toNat ↑↑n

Next tactic:
simp only [Int.toNat_coe_nat, le_refl]
/-- If the order has both a bot and a top, `toZ` gives an `OrderIso` between `ι` and
`Finset.range n` for some `n`. -/
def orderIsoRangeOfLinearSuccPredArch [OrderBot ι] [OrderTop ι] :
    ι ≃o Finset.range ((toZ ⊥ (⊤ : ι)).toNat + 1) where
  toFun i :=
    ⟨(toZ ⊥ i).toNat,
      Finset.mem_range_succ_iff.mpr (Int.toNat_le_toNat ((toZ_le_iff _ _).mpr le_top))⟩
  invFun n := succ^[n] ⊥
  left_inv i := iterate_succ_toZ i bot_le
  right_inv n := by
    ext1
    simp only [Subtype.coe_mk]
    refine' le_antisymm _ _
    · rw [Int.toNat_le]
      exact toZ_iterate_succ_le _
    by_cases hn_max : IsMax (succ^[↑n] (⊥ : ι))
    · rw [← isTop_iff_isMax, isTop_iff_eq_top] at hn_max
      rw [hn_max]
      exact Nat.lt_succ_iff.mp (Finset.mem_range.mp n.prop)
    · rw [toZ_iterate_succ_of_not_isMax _ hn_max]
      simp only [Int.toNat_coe_nat, le_refl]
  map_rel_iff' := by
    

Proof state:
ι : Type u_1
inst✝⁵ : LinearOrder ι
inst✝⁴ : SuccOrder ι
inst✝³ : PredOrder ι
inst✝² : IsSuccArchimedean ι
inst✝¹ : OrderBot ι
inst✝ : OrderTop ι
⊢ ∀ {a b : ι},
    {
            toFun := fun i =>
              { val := Int.toNat (toZ ⊥ i),
                property := (_ : Int.toNat (toZ ⊥ i) ∈ Finset.range (Nat.succ (Int.toNat (toZ ⊥ ⊤)))) },
            invFun := fun n => succ^[↑n] ⊥, left_inv := (_ : ∀ (i : ι), succ^[Int.toNat (toZ ⊥ i)] ⊥ = i),
            right_inv :=
              (_ :
                ∀ (n : { x // x ∈ Finset.range (Int.toNat (toZ ⊥ ⊤) + 1) }),
                  (fun i =>
                        { val := Int.toNat (toZ ⊥ i),
                          property := (_ : Int.toNat (toZ ⊥ i) ∈ Finset.range (Nat.succ (Int.toNat (toZ ⊥ ⊤)))) })
                      ((fun n => succ^[↑n] ⊥) n) =
                    n) }
          a ≤
        {
            toFun := fun i =>
              { val := Int.toNat (toZ ⊥ i),
                property := (_ : Int.toNat (toZ ⊥ i) ∈ Finset.range (Nat.succ (Int.toNat (toZ ⊥ ⊤)))) },
            invFun := fun n => succ^[↑n] ⊥, left_inv := (_ : ∀ (i : ι), succ^[Int.toNat (toZ ⊥ i)] ⊥ = i),
            right_inv :=
              (_ :
                ∀ (n : { x // x ∈ Finset.range (Int.toNat (toZ ⊥ ⊤) + 1) }),
                  (fun i =>
                        { val := Int.toNat (toZ ⊥ i),
                          property := (_ : Int.toNat (toZ ⊥ i) ∈ Finset.range (Nat.succ (Int.toNat (toZ ⊥ ⊤)))) })
                      ((fun n => succ^[↑n] ⊥) n) =
                    n) }
          b ↔
      a ≤ b

Next tactic:
intro i j
/-- If the order has both a bot and a top, `toZ` gives an `OrderIso` between `ι` and
`Finset.range n` for some `n`. -/
def orderIsoRangeOfLinearSuccPredArch [OrderBot ι] [OrderTop ι] :
    ι ≃o Finset.range ((toZ ⊥ (⊤ : ι)).toNat + 1) where
  toFun i :=
    ⟨(toZ ⊥ i).toNat,
      Finset.mem_range_succ_iff.mpr (Int.toNat_le_toNat ((toZ_le_iff _ _).mpr le_top))⟩
  invFun n := succ^[n] ⊥
  left_inv i := iterate_succ_toZ i bot_le
  right_inv n := by
    ext1
    simp only [Subtype.coe_mk]
    refine' le_antisymm _ _
    · rw [Int.toNat_le]
      exact toZ_iterate_succ_le _
    by_cases hn_max : IsMax (succ^[↑n] (⊥ : ι))
    · rw [← isTop_iff_isMax, isTop_iff_eq_top] at hn_max
      rw [hn_max]
      exact Nat.lt_succ_iff.mp (Finset.mem_range.mp n.prop)
    · rw [toZ_iterate_succ_of_not_isMax _ hn_max]
      simp only [Int.toNat_coe_nat, le_refl]
  map_rel_iff' := by
    intro i j
    

Proof state:
ι : Type u_1
inst✝⁵ : LinearOrder ι
inst✝⁴ : SuccOrder ι
inst✝³ : PredOrder ι
inst✝² : IsSuccArchimedean ι
inst✝¹ : OrderBot ι
inst✝ : OrderTop ι
i j : ι
⊢ {
          toFun := fun i =>
            { val := Int.toNat (toZ ⊥ i),
              property := (_ : Int.toNat (toZ ⊥ i) ∈ Finset.range (Nat.succ (Int.toNat (toZ ⊥ ⊤)))) },
          invFun := fun n => succ^[↑n] ⊥, left_inv := (_ : ∀ (i : ι), succ^[Int.toNat (toZ ⊥ i)] ⊥ = i),
          right_inv :=
            (_ :
              ∀ (n : { x // x ∈ Finset.range (Int.toNat (toZ ⊥ ⊤) + 1) }),
                (fun i =>
                      { val := Int.toNat (toZ ⊥ i),
                        property := (_ : Int.toNat (toZ ⊥ i) ∈ Finset.range (Nat.succ (Int.toNat (toZ ⊥ ⊤)))) })
                    ((fun n => succ^[↑n] ⊥) n) =
                  n) }
        i ≤
      {
          toFun := fun i =>
            { val := Int.toNat (toZ ⊥ i),
              property := (_ : Int.toNat (toZ ⊥ i) ∈ Finset.range (Nat.succ (Int.toNat (toZ ⊥ ⊤)))) },
          invFun := fun n => succ^[↑n] ⊥, left_inv := (_ : ∀ (i : ι), succ^[Int.toNat (toZ ⊥ i)] ⊥ = i),
          right_inv :=
            (_ :
              ∀ (n : { x // x ∈ Finset.range (Int.toNat (toZ ⊥ ⊤) + 1) }),
                (fun i =>
                      { val := Int.toNat (toZ ⊥ i),
                        property := (_ : Int.toNat (toZ ⊥ i) ∈ Finset.range (Nat.succ (Int.toNat (toZ ⊥ ⊤)))) })
                    ((fun n => succ^[↑n] ⊥) n) =
                  n) }
        j ↔
    i ≤ j

Next tactic:
simp only [Equiv.coe_fn_mk, Subtype.mk_le_mk, Int.toNat_le]
/-- If the order has both a bot and a top, `toZ` gives an `OrderIso` between `ι` and
`Finset.range n` for some `n`. -/
def orderIsoRangeOfLinearSuccPredArch [OrderBot ι] [OrderTop ι] :
    ι ≃o Finset.range ((toZ ⊥ (⊤ : ι)).toNat + 1) where
  toFun i :=
    ⟨(toZ ⊥ i).toNat,
      Finset.mem_range_succ_iff.mpr (Int.toNat_le_toNat ((toZ_le_iff _ _).mpr le_top))⟩
  invFun n := succ^[n] ⊥
  left_inv i := iterate_succ_toZ i bot_le
  right_inv n := by
    ext1
    simp only [Subtype.coe_mk]
    refine' le_antisymm _ _
    · rw [Int.toNat_le]
      exact toZ_iterate_succ_le _
    by_cases hn_max : IsMax (succ^[↑n] (⊥ : ι))
    · rw [← isTop_iff_isMax, isTop_iff_eq_top] at hn_max
      rw [hn_max]
      exact Nat.lt_succ_iff.mp (Finset.mem_range.mp n.prop)
    · rw [toZ_iterate_succ_of_not_isMax _ hn_max]
      simp only [Int.toNat_coe_nat, le_refl]
  map_rel_iff' := by
    intro i j
    simp only [Equiv.coe_fn_mk, Subtype.mk_le_mk, Int.toNat_le]
    

Proof state:
ι : Type u_1
inst✝⁵ : LinearOrder ι
inst✝⁴ : SuccOrder ι
inst✝³ : PredOrder ι
inst✝² : IsSuccArchimedean ι
inst✝¹ : OrderBot ι
inst✝ : OrderTop ι
i j : ι
⊢ toZ ⊥ i ≤ ↑(Int.toNat (toZ ⊥ j)) ↔ i ≤ j

Next tactic:
rw [← @toZ_le_iff ι _ _ _ _ ⊥, Int.toNat_of_nonneg (toZ_nonneg bot_le)]
theorem apply_firstDiff_ne {x y : ∀ n, E n} (h : x ≠ y) :
    x (firstDiff x y) ≠ y (firstDiff x y) := by
  

Proof state:
E : ℕ → Type u_1
x y : (n : ℕ) → E n
h : x ≠ y
⊢ x (firstDiff x y) ≠ y (firstDiff x y)

Next tactic:
rw [firstDiff_def, dif_pos h]
theorem apply_firstDiff_ne {x y : ∀ n, E n} (h : x ≠ y) :
    x (firstDiff x y) ≠ y (firstDiff x y) := by
  rw [firstDiff_def, dif_pos h]
  

Proof state:
E : ℕ → Type u_1
x y : (n : ℕ) → E n
h : x ≠ y
⊢ x (Nat.find (_ : ∃ a, x a ≠ y a)) ≠ y (Nat.find (_ : ∃ a, x a ≠ y a))

Next tactic:
exact Nat.find_spec (ne_iff.1 h)
theorem apply_eq_of_lt_firstDiff {x y : ∀ n, E n} {n : ℕ} (hn : n < firstDiff x y) : x n = y n := by
  

Proof state:
E : ℕ → Type u_1
x y : (n : ℕ) → E n
n : ℕ
hn : n < firstDiff x y
⊢ x n = y n

Next tactic:
rw [firstDiff_def] at hn
theorem apply_eq_of_lt_firstDiff {x y : ∀ n, E n} {n : ℕ} (hn : n < firstDiff x y) : x n = y n := by
  rw [firstDiff_def] at hn
  

Proof state:
E : ℕ → Type u_1
x y : (n : ℕ) → E n
n : ℕ
hn : n < if h : x ≠ y then Nat.find (_ : ∃ a, x a ≠ y a) else 0
⊢ x n = y n

Next tactic:
split_ifs at hn with h
theorem apply_eq_of_lt_firstDiff {x y : ∀ n, E n} {n : ℕ} (hn : n < firstDiff x y) : x n = y n := by
  rw [firstDiff_def] at hn
  split_ifs at hn with h
  · 

Proof state:
case pos
E : ℕ → Type u_1
x y : (n : ℕ) → E n
n : ℕ
h : x ≠ y
hn : n < Nat.find (_ : ∃ a, x a ≠ y a)
⊢ x n = y n

Next tactic:
convert Nat.find_min (ne_iff.1 h) hn
theorem apply_eq_of_lt_firstDiff {x y : ∀ n, E n} {n : ℕ} (hn : n < firstDiff x y) : x n = y n := by
  rw [firstDiff_def] at hn
  split_ifs at hn with h
  · convert Nat.find_min (ne_iff.1 h) hn
    

Proof state:
case a
E : ℕ → Type u_1
x y : (n : ℕ) → E n
n : ℕ
h : x ≠ y
hn : n < Nat.find (_ : ∃ a, x a ≠ y a)
⊢ x n = y n ↔ ¬x n ≠ y n

Next tactic:
simp
theorem apply_eq_of_lt_firstDiff {x y : ∀ n, E n} {n : ℕ} (hn : n < firstDiff x y) : x n = y n := by
  rw [firstDiff_def] at hn
  split_ifs at hn with h
  · convert Nat.find_min (ne_iff.1 h) hn
    simp
  · 

Proof state:
case neg
E : ℕ → Type u_1
x y : (n : ℕ) → E n
n : ℕ
h : ¬x ≠ y
hn : n < 0
⊢ x n = y n

Next tactic:
exact (not_lt_zero' hn).elim
theorem firstDiff_comm (x y : ∀ n, E n) : firstDiff x y = firstDiff y x := by
  

Proof state:
E : ℕ → Type u_1
x y : (n : ℕ) → E n
⊢ firstDiff x y = firstDiff y x

Next tactic:
simp only [firstDiff_def, ne_comm]
theorem min_firstDiff_le (x y z : ∀ n, E n) (h : x ≠ z) :
    min (firstDiff x y) (firstDiff y z) ≤ firstDiff x z := by
  

Proof state:
E : ℕ → Type u_1
x y z : (n : ℕ) → E n
h : x ≠ z
⊢ min (firstDiff x y) (firstDiff y z) ≤ firstDiff x z

Next tactic:
by_contra! H
theorem min_firstDiff_le (x y z : ∀ n, E n) (h : x ≠ z) :
    min (firstDiff x y) (firstDiff y z) ≤ firstDiff x z := by
  by_contra! H
  

Proof state:
E : ℕ → Type u_1
x y z : (n : ℕ) → E n
h : x ≠ z
H : firstDiff x z < min (firstDiff x y) (firstDiff y z)
⊢ False

Next tactic:
rw [lt_min_iff] at H
theorem min_firstDiff_le (x y z : ∀ n, E n) (h : x ≠ z) :
    min (firstDiff x y) (firstDiff y z) ≤ firstDiff x z := by
  by_contra! H
  rw [lt_min_iff] at H
  

Proof state:
E : ℕ → Type u_1
x y z : (n : ℕ) → E n
h : x ≠ z
H : firstDiff x z < firstDiff x y ∧ firstDiff x z < firstDiff y z
⊢ False

Next tactic:
refine apply_firstDiff_ne h ?_
theorem min_firstDiff_le (x y z : ∀ n, E n) (h : x ≠ z) :
    min (firstDiff x y) (firstDiff y z) ≤ firstDiff x z := by
  by_contra! H
  rw [lt_min_iff] at H
  refine apply_firstDiff_ne h ?_
  

Proof state:
E : ℕ → Type u_1
x y z : (n : ℕ) → E n
h : x ≠ z
H : firstDiff x z < firstDiff x y ∧ firstDiff x z < firstDiff y z
⊢ x (firstDiff x z) = z (firstDiff x z)

Next tactic:
calc
    x (firstDiff x z) = y (firstDiff x z) := apply_eq_of_lt_firstDiff H.1
    _ = z (firstDiff x z) := apply_eq_of_lt_firstDiff H.2
theorem cylinder_eq_pi (x : ∀ n, E n) (n : ℕ) :
    cylinder x n = Set.pi (Finset.range n : Set ℕ) fun i : ℕ => {x i} := by
  

Proof state:
E : ℕ → Type u_1
x : (n : ℕ) → E n
n : ℕ
⊢ cylinder x n = Set.pi ↑(Finset.range n) fun i => {x i}

Next tactic:
ext y
theorem cylinder_eq_pi (x : ∀ n, E n) (n : ℕ) :
    cylinder x n = Set.pi (Finset.range n : Set ℕ) fun i : ℕ => {x i} := by
  ext y
  

Proof state:
case h
E : ℕ → Type u_1
x : (n : ℕ) → E n
n : ℕ
y : (n : ℕ) → E n
⊢ y ∈ cylinder x n ↔ y ∈ Set.pi ↑(Finset.range n) fun i => {x i}

Next tactic:
simp [cylinder]
@[simp]
theorem cylinder_zero (x : ∀ n, E n) : cylinder x 0 = univ := by 

Proof state:
E : ℕ → Type u_1
x : (n : ℕ) → E n
⊢ cylinder x 0 = univ

Next tactic:
simp [cylinder_eq_pi]
theorem self_mem_cylinder (x : ∀ n, E n) (n : ℕ) : x ∈ cylinder x n := by 

Proof state:
E : ℕ → Type u_1
x : (n : ℕ) → E n
n : ℕ
⊢ x ∈ cylinder x n

Next tactic:
simp
theorem mem_cylinder_iff_eq {x y : ∀ n, E n} {n : ℕ} :
    y ∈ cylinder x n ↔ cylinder y n = cylinder x n := by
  

Proof state:
E : ℕ → Type u_1
x y : (n : ℕ) → E n
n : ℕ
⊢ y ∈ cylinder x n ↔ cylinder y n = cylinder x n

Next tactic:
constructor
theorem mem_cylinder_iff_eq {x y : ∀ n, E n} {n : ℕ} :
    y ∈ cylinder x n ↔ cylinder y n = cylinder x n := by
  constructor
  · 

Proof state:
case mp
E : ℕ → Type u_1
x y : (n : ℕ) → E n
n : ℕ
⊢ y ∈ cylinder x n → cylinder y n = cylinder x n

Next tactic:
intro hy
theorem mem_cylinder_iff_eq {x y : ∀ n, E n} {n : ℕ} :
    y ∈ cylinder x n ↔ cylinder y n = cylinder x n := by
  constructor
  · intro hy
    

Proof state:
case mp
E : ℕ → Type u_1
x y : (n : ℕ) → E n
n : ℕ
hy : y ∈ cylinder x n
⊢ cylinder y n = cylinder x n

Next tactic:
apply Subset.antisymm