l3lab/ntp-mathlib huggingface dataset:
/-- Given a sequence of continuous linear maps which converges pointwise and for which the
domain is barrelled, the Banach-Steinhaus theorem is used to guarantee that the limit map
is a *continuous* linear map as well.

This actually works for any *countably generated* filter instead of `atTop : Filter ℕ`,
but the proof ultimately goes back to sequences. -/
protected def continuousLinearMapOfTendsto [T2Space F] {l : Filter α} [l.IsCountablyGenerated]
    [l.NeBot] (g : α → E →SL[σ₁₂] F) {f : E → F} (h : Tendsto (fun n x ↦ g n x) l (𝓝 f)) :
    E →SL[σ₁₂] F where
  toLinearMap := linearMapOfTendsto _ _ h
  cont := by
    -- Since the filter `l` is countably generated and nontrivial, we can find a sequence
    -- `u : ℕ → α` that tends to `l`. By considering `g ∘ u` instead of `g`, we can thus assume
    -- that `α = ℕ` and `l = atTop`
    rcases l.exists_seq_tendsto with ⟨u, hu⟩
    -- We claim that the limit is continuous because it's a limit of an equicontinuous family.
    -- By the Banach-Steinhaus theorem, this equicontinuity will follow from pointwise boundedness.
    refine (h.comp hu).continuous_of_equicontinuousAt (hq.banach_steinhaus ?_).equicontinuous
    -- For `k` and `x` fixed, we need to show that `(i : ℕ) ↦ q k (g i x)` is bounded.
    intro k x
    -- This follows from the fact that this sequences converges (to `q k (f x)`) by hypothesis and
    -- continuity of `q k`.
    rw [tendsto_pi_nhds] at h
    

Proof state:
case intro
α : Type u_1
ι : Type u_2
κ : Type u_3
𝕜₁ : Type u_4
𝕜₂ : Type u_5
E : Type u_6
F : Type u_7
inst✝¹⁷ : Nonempty κ
inst✝¹⁶ : NontriviallyNormedField 𝕜₁
inst✝¹⁵ : NontriviallyNormedField 𝕜₂
σ₁₂ : 𝕜₁ →+* 𝕜₂
inst✝¹⁴ : RingHomIsometric σ₁₂
inst✝¹³ : AddCommGroup E
inst✝¹² : AddCommGroup F
inst✝¹¹ : Module 𝕜₁ E
inst✝¹⁰ : Module 𝕜₂ F
inst✝⁹ : UniformSpace E
inst✝⁸ : UniformSpace F
inst✝⁷ : UniformAddGroup E
inst✝⁶ : UniformAddGroup F
inst✝⁵ : ContinuousSMul 𝕜₁ E
inst✝⁴ : ContinuousSMul 𝕜₂ F
inst✝³ : BarrelledSpace 𝕜₁ E
𝓕 : ι → E →SL[σ₁₂] F
q : SeminormFamily 𝕜₂ F κ
hq : WithSeminorms q
inst✝² : T2Space F
l : Filter α
inst✝¹ : IsCountablyGenerated l
inst✝ : NeBot l
g : α → E →SL[σ₁₂] F
f : E → F
h : ∀ (x : E), Tendsto (fun i => (g i) x) l (𝓝 (f x))
u : ℕ → α
hu : Tendsto u atTop l
k : κ
x : E
⊢ BddAbove (range fun i => (q k) ((g (u i)) x))

Next tactic:
exact (((hq.continuous_seminorm k).tendsto _).comp <| (h x).comp hu).bddAbove_range
/-- An arrow in the groupoid defines, by conjugation, an isomorphism of groups between
its endpoints.
-/
@[simps]
def vertexGroupIsomOfMap {c d : C} (f : c ⟶ d) : (c ⟶ c) ≃* (d ⟶ d)
    where
  toFun γ := inv f ≫ γ ≫ f
  invFun δ := f ≫ δ ≫ inv f
  left_inv γ := by
    

Proof state:
C : Type u
inst✝ : Groupoid C
c d : C
f : c ⟶ d
γ : c ⟶ c
⊢ (fun δ => f ≫ δ ≫ inv f) ((fun γ => inv f ≫ γ ≫ f) γ) = γ

Next tactic:
simp_rw [Category.assoc, comp_inv, Category.comp_id, ← Category.assoc, comp_inv,
      Category.id_comp]
/-- An arrow in the groupoid defines, by conjugation, an isomorphism of groups between
its endpoints.
-/
@[simps]
def vertexGroupIsomOfMap {c d : C} (f : c ⟶ d) : (c ⟶ c) ≃* (d ⟶ d)
    where
  toFun γ := inv f ≫ γ ≫ f
  invFun δ := f ≫ δ ≫ inv f
  left_inv γ := by
    simp_rw [Category.assoc, comp_inv, Category.comp_id, ← Category.assoc, comp_inv,
      Category.id_comp]
  right_inv δ := by
    

Proof state:
C : Type u
inst✝ : Groupoid C
c d : C
f : c ⟶ d
δ : d ⟶ d
⊢ (fun γ => inv f ≫ γ ≫ f) ((fun δ => f ≫ δ ≫ inv f) δ) = δ

Next tactic:
simp_rw [Category.assoc, inv_comp, ← Category.assoc, inv_comp, Category.id_comp,
      Category.comp_id]
/-- An arrow in the groupoid defines, by conjugation, an isomorphism of groups between
its endpoints.
-/
@[simps]
def vertexGroupIsomOfMap {c d : C} (f : c ⟶ d) : (c ⟶ c) ≃* (d ⟶ d)
    where
  toFun γ := inv f ≫ γ ≫ f
  invFun δ := f ≫ δ ≫ inv f
  left_inv γ := by
    simp_rw [Category.assoc, comp_inv, Category.comp_id, ← Category.assoc, comp_inv,
      Category.id_comp]
  right_inv δ := by
    simp_rw [Category.assoc, inv_comp, ← Category.assoc, inv_comp, Category.id_comp,
      Category.comp_id]
  map_mul' γ₁ γ₂ := by
    

Proof state:
C : Type u
inst✝ : Groupoid C
c d : C
f : c ⟶ d
γ₁ γ₂ : c ⟶ c
⊢ Equiv.toFun
      { toFun := fun γ => inv f ≫ γ ≫ f, invFun := fun δ => f ≫ δ ≫ inv f,
        left_inv := (_ : ∀ (γ : c ⟶ c), (fun δ => f ≫ δ ≫ inv f) ((fun γ => inv f ≫ γ ≫ f) γ) = γ),
        right_inv := (_ : ∀ (δ : d ⟶ d), (fun γ => inv f ≫ γ ≫ f) ((fun δ => f ≫ δ ≫ inv f) δ) = δ) }
      (γ₁ * γ₂) =
    Equiv.toFun
        { toFun := fun γ => inv f ≫ γ ≫ f, invFun := fun δ => f ≫ δ ≫ inv f,
          left_inv := (_ : ∀ (γ : c ⟶ c), (fun δ => f ≫ δ ≫ inv f) ((fun γ => inv f ≫ γ ≫ f) γ) = γ),
          right_inv := (_ : ∀ (δ : d ⟶ d), (fun γ => inv f ≫ γ ≫ f) ((fun δ => f ≫ δ ≫ inv f) δ) = δ) }
        γ₁ *
      Equiv.toFun
        { toFun := fun γ => inv f ≫ γ ≫ f, invFun := fun δ => f ≫ δ ≫ inv f,
          left_inv := (_ : ∀ (γ : c ⟶ c), (fun δ => f ≫ δ ≫ inv f) ((fun γ => inv f ≫ γ ≫ f) γ) = γ),
          right_inv := (_ : ∀ (δ : d ⟶ d), (fun γ => inv f ≫ γ ≫ f) ((fun δ => f ≫ δ ≫ inv f) δ) = δ) }
        γ₂

Next tactic:
simp only [vertexGroup_mul, inv_eq_inv, Category.assoc, IsIso.hom_inv_id_assoc]
/-- Two `v w : Vector α n` are equal iff they are equal at every single index. -/
@[ext]
theorem ext : ∀ {v w : Vector α n} (_ : ∀ m : Fin n, Vector.get v m = Vector.get w m), v = w
  | ⟨v, hv⟩, ⟨w, hw⟩, h =>
    Subtype.eq (List.ext_get (by 

Proof state:
n : ℕ
α : Type u_1
v : List α
hv : List.length v = n
w : List α
hw : List.length w = n
h : ∀ (m : Fin n), get { val := v, property := hv } m = get { val := w, property := hw } m
⊢ List.length ↑{ val := v, property := hv } = List.length ↑{ val := w, property := hw }

Next tactic:
rw [hv, hw]
theorem eq_cons_iff (a : α) (v : Vector α n.succ) (v' : Vector α n) :
    v = a ::ᵥ v' ↔ v.head = a ∧ v.tail = v' :=
  ⟨fun h => h.symm ▸ ⟨head_cons a v', tail_cons a v'⟩, fun h =>
    _root_.trans (cons_head_tail v).symm (by 

Proof state:
n : ℕ
α : Type u_1
a : α
v : Vector α (Nat.succ n)
v' : Vector α n
h : head v = a ∧ tail v = v'
⊢ head v ::ᵥ tail v = a ::ᵥ v'

Next tactic:
rw [h.1, h.2]
theorem ne_cons_iff (a : α) (v : Vector α n.succ) (v' : Vector α n) :
    v ≠ a ::ᵥ v' ↔ v.head ≠ a ∨ v.tail ≠ v' := by 

Proof state:
n : ℕ
α : Type u_1
a : α
v : Vector α (Nat.succ n)
v' : Vector α n
⊢ v ≠ a ::ᵥ v' ↔ head v ≠ a ∨ tail v ≠ v'

Next tactic:
rw [Ne.def, eq_cons_iff a v v', not_and_or]
@[simp]
theorem toList_ofFn : ∀ {n} (f : Fin n → α), toList (ofFn f) = List.ofFn f
  | 0, f => rfl
  | n + 1, f => by 

Proof state:
n✝ : ℕ
α : Type u_1
n : ℕ
f : Fin (n + 1) → α
⊢ toList (ofFn f) = List.ofFn f

Next tactic:
rw [ofFn, List.ofFn_succ, toList_cons, toList_ofFn]
@[simp]
theorem toList_map {β : Type*} (v : Vector α n) (f : α → β) : (v.map f).toList = v.toList.map f :=
  by 

Proof state:
n : ℕ
α : Type u_1
β : Type u_2
v : Vector α n
f : α → β
⊢ toList (map f v) = List.map f (toList v)

Next tactic:
cases v
@[simp]
theorem toList_map {β : Type*} (v : Vector α n) (f : α → β) : (v.map f).toList = v.toList.map f :=
  by cases v; 

Proof state:
case mk
n : ℕ
α : Type u_1
β : Type u_2
f : α → β
val✝ : List α
property✝ : List.length val✝ = n
⊢ toList (map f { val := val✝, property := property✝ }) = List.map f (toList { val := val✝, property := property✝ })

Next tactic:
rfl
@[simp]
theorem head_map {β : Type*} (v : Vector α (n + 1)) (f : α → β) : (v.map f).head = f v.head := by
  

Proof state:
n : ℕ
α : Type u_1
β : Type u_2
v : Vector α (n + 1)
f : α → β
⊢ head (map f v) = f (head v)

Next tactic:
obtain ⟨a, v', h⟩ := Vector.exists_eq_cons v
@[simp]
theorem head_map {β : Type*} (v : Vector α (n + 1)) (f : α → β) : (v.map f).head = f v.head := by
  obtain ⟨a, v', h⟩ := Vector.exists_eq_cons v
  

Proof state:
case intro.intro
n : ℕ
α : Type u_1
β : Type u_2
v : Vector α (n + 1)
f : α → β
a : α
v' : Vector α n
h : v = a ::ᵥ v'
⊢ head (map f v) = f (head v)

Next tactic:
rw [h, map_cons, head_cons, head_cons]
@[simp]
theorem tail_map {β : Type*} (v : Vector α (n + 1)) (f : α → β) :
    (v.map f).tail = v.tail.map f := by
  

Proof state:
n : ℕ
α : Type u_1
β : Type u_2
v : Vector α (n + 1)
f : α → β
⊢ tail (map f v) = map f (tail v)

Next tactic:
obtain ⟨a, v', h⟩ := Vector.exists_eq_cons v
@[simp]
theorem tail_map {β : Type*} (v : Vector α (n + 1)) (f : α → β) :
    (v.map f).tail = v.tail.map f := by
  obtain ⟨a, v', h⟩ := Vector.exists_eq_cons v
  

Proof state:
case intro.intro
n : ℕ
α : Type u_1
β : Type u_2
v : Vector α (n + 1)
f : α → β
a : α
v' : Vector α n
h : v = a ::ᵥ v'
⊢ tail (map f v) = map f (tail v)

Next tactic:
rw [h, map_cons, tail_cons, tail_cons]
@[deprecated get_eq_get]
theorem nth_eq_nthLe :
    ∀ (v : Vector α n) (i), get v i = v.toList.nthLe i.1 (by 

Proof state:
n : ℕ
α : Type u_1
v : Vector α n
i : Fin n
⊢ ↑i < List.length (toList v)

Next tactic:
rw [toList_length]
@[deprecated get_eq_get]
theorem nth_eq_nthLe :
    ∀ (v : Vector α n) (i), get v i = v.toList.nthLe i.1 (by rw [toList_length]; 

Proof state:
n : ℕ
α : Type u_1
v : Vector α n
i : Fin n
⊢ ↑i < n

Next tactic:
exact i.2
@[simp]
theorem get_replicate (a : α) (i : Fin n) : (Vector.replicate n a).get i = a := by
  

Proof state:
n : ℕ
α : Type u_1
a : α
i : Fin n
⊢ get (replicate n a) i = a

Next tactic:
apply List.get_replicate
@[simp]
theorem get_map {β : Type*} (v : Vector α n) (f : α → β) (i : Fin n) :
    (v.map f).get i = f (v.get i) := by
  

Proof state:
n : ℕ
α : Type u_1
β : Type u_2
v : Vector α n
f : α → β
i : Fin n
⊢ get (map f v) i = f (get v i)

Next tactic:
cases v
@[simp]
theorem get_map {β : Type*} (v : Vector α n) (f : α → β) (i : Fin n) :
    (v.map f).get i = f (v.get i) := by
  cases v; 

Proof state:
case mk
n : ℕ
α : Type u_1
β : Type u_2
f : α → β
i : Fin n
val✝ : List α
property✝ : List.length val✝ = n
⊢ get (map f { val := val✝, property := property✝ }) i = f (get { val := val✝, property := property✝ } i)

Next tactic:
simp [Vector.map, get_eq_get]
@[simp]
theorem get_map {β : Type*} (v : Vector α n) (f : α → β) (i : Fin n) :
    (v.map f).get i = f (v.get i) := by
  cases v; simp [Vector.map, get_eq_get]; 

Proof state:
case mk
n : ℕ
α : Type u_1
β : Type u_2
f : α → β
i : Fin n
val✝ : List α
property✝ : List.length val✝ = n
⊢ f (List.get val✝ { val := ↑i, isLt := (_ : ↑i < List.length val✝) }) =
    f (List.get val✝ (Fin.cast (_ : n = List.length (toList { val := val✝, property := property✝ })) i))

Next tactic:
rfl
@[simp]
theorem get_ofFn {n} (f : Fin n → α) (i) : get (ofFn f) i = f i := by
  

Proof state:
n✝ : ℕ
α : Type u_1
n : ℕ
f : Fin n → α
i : Fin n
⊢ get (ofFn f) i = f i

Next tactic:
conv_rhs => erw [← List.get_ofFn f ⟨i, by simp⟩]
@[simp]
theorem get_ofFn {n} (f : Fin n → α) (i) : get (ofFn f) i = f i := by
  conv_rhs => 

Proof state:
n✝ : ℕ
α : Type u_1
n : ℕ
f : Fin n → α
i : Fin n
| f i

Next tactic:
erw [← List.get_ofFn f ⟨i, by simp⟩]
@[simp]
theorem get_ofFn {n} (f : Fin n → α) (i) : get (ofFn f) i = f i := by
  conv_rhs => erw [← List.get_ofFn f ⟨i, by 

Proof state:
n✝ : ℕ
α : Type u_1
n : ℕ
f : Fin n → α
i : Fin n
⊢ ↑i < List.length (List.ofFn f)

Next tactic:
simp
@[simp]
theorem get_ofFn {n} (f : Fin n → α) (i) : get (ofFn f) i = f i := by
  conv_rhs => erw [← List.get_ofFn f ⟨i, by simp⟩]
  

Proof state:
n✝ : ℕ
α : Type u_1
n : ℕ
f : Fin n → α
i : Fin n
⊢ get (ofFn f) i = List.get (List.ofFn f) { val := ↑i, isLt := (_ : ↑i < List.length (List.ofFn f)) }

Next tactic:
simp only [get_eq_get]
@[simp]
theorem get_ofFn {n} (f : Fin n → α) (i) : get (ofFn f) i = f i := by
  conv_rhs => erw [← List.get_ofFn f ⟨i, by simp⟩]
  simp only [get_eq_get]
  

Proof state:
n✝ : ℕ
α : Type u_1
n : ℕ
f : Fin n → α
i : Fin n
⊢ List.get (toList (ofFn f)) (Fin.cast (_ : n = List.length (toList (ofFn f))) i) =
    List.get (List.ofFn f) { val := ↑i, isLt := (_ : ↑i < List.length (List.ofFn f)) }

Next tactic:
congr
@[simp]
theorem get_ofFn {n} (f : Fin n → α) (i) : get (ofFn f) i = f i := by
  conv_rhs => erw [← List.get_ofFn f ⟨i, by simp⟩]
  simp only [get_eq_get]
  congr <;> 

Proof state:
case h.e_2.h
n✝ : ℕ
α : Type u_1
n : ℕ
f : Fin n → α
i : Fin n
⊢ toList (ofFn f) = List.ofFn f

Next tactic:
simp [Fin.heq_ext_iff]
@[simp]
theorem get_ofFn {n} (f : Fin n → α) (i) : get (ofFn f) i = f i := by
  conv_rhs => erw [← List.get_ofFn f ⟨i, by simp⟩]
  simp only [get_eq_get]
  congr <;> 

Proof state:
case h.e_3.e_2.e_a
n✝ : ℕ
α : Type u_1
n : ℕ
f : Fin n → α
i : Fin n
⊢ toList (ofFn f) = List.ofFn f

Next tactic:
simp [Fin.heq_ext_iff]
@[simp]
theorem get_ofFn {n} (f : Fin n → α) (i) : get (ofFn f) i = f i := by
  conv_rhs => erw [← List.get_ofFn f ⟨i, by simp⟩]
  simp only [get_eq_get]
  congr <;> 

Proof state:
case h.e_3.e_3.e_2.h.e_a
n✝ : ℕ
α : Type u_1
n : ℕ
f : Fin n → α
i : Fin n
h_congr_thm✝ :
  ∀ (n n' : ℕ),
    n = n' →
      ∀ (m m' : ℕ),
        m = m' →
          ∀ (eq : n = m) (eq' : n' = m'),
            HEq eq eq' → ∀ (i : Fin n) (i' : Fin n'), HEq i i' → HEq (Fin.cast eq i) (Fin.cast eq' i')
⊢ toList (ofFn f) = List.ofFn f

Next tactic:
simp [Fin.heq_ext_iff]
@[simp]
theorem get_ofFn {n} (f : Fin n → α) (i) : get (ofFn f) i = f i := by
  conv_rhs => erw [← List.get_ofFn f ⟨i, by simp⟩]
  simp only [get_eq_get]
  congr <;> 

Proof state:
case h.e_3.e_3.e_4
n✝ : ℕ
α : Type u_1
n : ℕ
f : Fin n → α
i : Fin n
h_congr_thm✝¹ :
  ∀ (n n' : ℕ),
    n = n' →
      ∀ (m m' : ℕ),
        m = m' →
          ∀ (eq : n = m) (eq' : n' = m'),
            HEq eq eq' → ∀ (i : Fin n) (i' : Fin n'), HEq i i' → HEq (Fin.cast eq i) (Fin.cast eq' i')
h_congr_thm✝ :
  ∀ (α α' : Type),
    α = α' →
      ∀ (a : α) (a' : α'),
        HEq a a' →
          ∀ (b : α) (b' : α'), HEq b b' → ∀ (h : a = b) (h' : a' = b'), HEq h h' → HEq (_ : b = a) (_ : b' = a')
⊢ HEq ?h.e_3.e_3.h ?h.e_3.e_3.h'

Next tactic:
simp [Fin.heq_ext_iff]
@[simp]
theorem get_ofFn {n} (f : Fin n → α) (i) : get (ofFn f) i = f i := by
  conv_rhs => erw [← List.get_ofFn f ⟨i, by simp⟩]
  simp only [get_eq_get]
  congr <;> 

Proof state:
case h.e_3.e_3.h
n✝ : ℕ
α : Type u_1
n : ℕ
f : Fin n → α
i : Fin n
h_congr_thm✝ :
  ∀ (n n' : ℕ),
    n = n' →
      ∀ (m m' : ℕ),
        m = m' →
          ∀ (eq : n = m) (eq' : n' = m'),
            HEq eq eq' → ∀ (i : Fin n) (i' : Fin n'), HEq i i' → HEq (Fin.cast eq i) (Fin.cast eq' i')
⊢ List.length (toList (ofFn f)) = n

Next tactic:
simp [Fin.heq_ext_iff]
@[simp]
theorem get_ofFn {n} (f : Fin n → α) (i) : get (ofFn f) i = f i := by
  conv_rhs => erw [← List.get_ofFn f ⟨i, by simp⟩]
  simp only [get_eq_get]
  congr <;> 

Proof state:
case h.e_3.e_3.h'
n✝ : ℕ
α : Type u_1
n : ℕ
f : Fin n → α
i : Fin n
h_congr_thm✝ :
  ∀ (n n' : ℕ),
    n = n' →
      ∀ (m m' : ℕ),
        m = m' →
          ∀ (eq : n = m) (eq' : n' = m'),
            HEq eq eq' → ∀ (i : Fin n) (i' : Fin n'), HEq i i' → HEq (Fin.cast eq i) (Fin.cast eq' i')
⊢ List.length (List.ofFn f) = n

Next tactic:
simp [Fin.heq_ext_iff]
@[simp]
theorem get_ofFn {n} (f : Fin n → α) (i) : get (ofFn f) i = f i := by
  conv_rhs => erw [← List.get_ofFn f ⟨i, by simp⟩]
  simp only [get_eq_get]
  congr <;> 

Proof state:
case h.e_3.eq'
n✝ : ℕ
α : Type u_1
n : ℕ
f : Fin n → α
i : Fin n
⊢ n = List.length (List.ofFn f)

Next tactic:
simp [Fin.heq_ext_iff]
@[simp]
theorem ofFn_get (v : Vector α n) : ofFn (get v) = v := by
  

Proof state:
n : ℕ
α : Type u_1
v : Vector α n
⊢ ofFn (get v) = v

Next tactic:
rcases v with ⟨l, rfl⟩
@[simp]
theorem ofFn_get (v : Vector α n) : ofFn (get v) = v := by
  rcases v with ⟨l, rfl⟩
  

Proof state:
case mk
α : Type u_1
l : List α
⊢ ofFn (get { val := l, property := (_ : List.length l = List.length l) }) =
    { val := l, property := (_ : List.length l = List.length l) }

Next tactic:
apply toList_injective
@[simp]
theorem ofFn_get (v : Vector α n) : ofFn (get v) = v := by
  rcases v with ⟨l, rfl⟩
  apply toList_injective
  

Proof state:
case mk.a
α : Type u_1
l : List α
⊢ toList (ofFn (get { val := l, property := (_ : List.length l = List.length l) })) =
    toList { val := l, property := (_ : List.length l = List.length l) }

Next tactic:
dsimp
@[simp]
theorem ofFn_get (v : Vector α n) : ofFn (get v) = v := by
  rcases v with ⟨l, rfl⟩
  apply toList_injective
  dsimp
  

Proof state:
case mk.a
α : Type u_1
l : List α
⊢ toList (ofFn (get { val := l, property := (_ : List.length l = List.length l) })) = l

Next tactic:
simpa only [toList_ofFn] using List.ofFn_get _
theorem get_tail (x : Vector α n) (i) :
    x.tail.get i = x.get ⟨i.1 + 1, lt_tsub_iff_right.mp i.2⟩ := by
  

Proof state:
n : ℕ
α : Type u_1
x : Vector α n
i : Fin (n - 1)
⊢ get (tail x) i = get x { val := ↑i + 1, isLt := (_ : ↑i + 1 < n) }

Next tactic:
cases' i with i ih
theorem get_tail (x : Vector α n) (i) :
    x.tail.get i = x.get ⟨i.1 + 1, lt_tsub_iff_right.mp i.2⟩ := by
  cases' i with i ih; 

Proof state:
case mk
n : ℕ
α : Type u_1
x : Vector α n
i : ℕ
ih : i < n - 1
⊢ get (tail x) { val := i, isLt := ih } =
    get x { val := ↑{ val := i, isLt := ih } + 1, isLt := (_ : ↑{ val := i, isLt := ih } + 1 < n) }

Next tactic:
dsimp
theorem get_tail (x : Vector α n) (i) :
    x.tail.get i = x.get ⟨i.1 + 1, lt_tsub_iff_right.mp i.2⟩ := by
  cases' i with i ih; dsimp
  

Proof state:
case mk
n : ℕ
α : Type u_1
x : Vector α n
i : ℕ
ih : i < n - 1
⊢ get (tail x) { val := i, isLt := ih } = get x { val := i + 1, isLt := (_ : i + 1 < n) }

Next tactic:
rcases x with ⟨_ | _, h⟩
theorem get_tail (x : Vector α n) (i) :
    x.tail.get i = x.get ⟨i.1 + 1, lt_tsub_iff_right.mp i.2⟩ := by
  cases' i with i ih; dsimp
  rcases x with ⟨_ | _, h⟩ <;> 

Proof state:
case mk.mk.nil
n : ℕ
α : Type u_1
i : ℕ
ih : i < n - 1
h : List.length [] = n
⊢ get (tail { val := [], property := h }) { val := i, isLt := ih } =
    get { val := [], property := h } { val := i + 1, isLt := (_ : i + 1 < n) }

Next tactic:
try rfl
theorem get_tail (x : Vector α n) (i) :
    x.tail.get i = x.get ⟨i.1 + 1, lt_tsub_iff_right.mp i.2⟩ := by
  cases' i with i ih; dsimp
  rcases x with ⟨_ | _, h⟩ <;> try 

Proof state:
case mk.mk.nil
n : ℕ
α : Type u_1
i : ℕ
ih : i < n - 1
h : List.length [] = n
⊢ get (tail { val := [], property := h }) { val := i, isLt := ih } =
    get { val := [], property := h } { val := i + 1, isLt := (_ : i + 1 < n) }

Next tactic:
rfl
theorem get_tail (x : Vector α n) (i) :
    x.tail.get i = x.get ⟨i.1 + 1, lt_tsub_iff_right.mp i.2⟩ := by
  cases' i with i ih; dsimp
  rcases x with ⟨_ | _, h⟩ <;> 

Proof state:
case mk.mk.cons
n : ℕ
α : Type u_1
i : ℕ
ih : i < n - 1
head✝ : α
tail✝ : List α
h : List.length (head✝ :: tail✝) = n
⊢ get (tail { val := head✝ :: tail✝, property := h }) { val := i, isLt := ih } =
    get { val := head✝ :: tail✝, property := h } { val := i + 1, isLt := (_ : i + 1 < n) }

Next tactic:
try rfl
theorem get_tail (x : Vector α n) (i) :
    x.tail.get i = x.get ⟨i.1 + 1, lt_tsub_iff_right.mp i.2⟩ := by
  cases' i with i ih; dsimp
  rcases x with ⟨_ | _, h⟩ <;> try 

Proof state:
case mk.mk.cons
n : ℕ
α : Type u_1
i : ℕ
ih : i < n - 1
head✝ : α
tail✝ : List α
h : List.length (head✝ :: tail✝) = n
⊢ get (tail { val := head✝ :: tail✝, property := h }) { val := i, isLt := ih } =
    get { val := head✝ :: tail✝, property := h } { val := i + 1, isLt := (_ : i + 1 < n) }

Next tactic:
rfl
theorem get_tail (x : Vector α n) (i) :
    x.tail.get i = x.get ⟨i.1 + 1, lt_tsub_iff_right.mp i.2⟩ := by
  cases' i with i ih; dsimp
  rcases x with ⟨_ | _, h⟩ <;> try rfl
  

Proof state:
case mk.mk.nil
n : ℕ
α : Type u_1
i : ℕ
ih : i < n - 1
h : List.length [] = n
⊢ get (tail { val := [], property := h }) { val := i, isLt := ih } =
    get { val := [], property := h } { val := i + 1, isLt := (_ : i + 1 < n) }

Next tactic:
rw [List.length] at h
theorem get_tail (x : Vector α n) (i) :
    x.tail.get i = x.get ⟨i.1 + 1, lt_tsub_iff_right.mp i.2⟩ := by
  cases' i with i ih; dsimp
  rcases x with ⟨_ | _, h⟩ <;> try rfl
  rw [List.length] at h
  

Proof state:
case mk.mk.nil
n : ℕ
α : Type u_1
i : ℕ
ih : i < n - 1
h✝ : List.length [] = n
h : 0 = n
⊢ get (tail { val := [], property := h✝ }) { val := i, isLt := ih } =
    get { val := [], property := h✝ } { val := i + 1, isLt := (_ : i + 1 < n) }

Next tactic:
rw [← h] at ih
theorem get_tail (x : Vector α n) (i) :
    x.tail.get i = x.get ⟨i.1 + 1, lt_tsub_iff_right.mp i.2⟩ := by
  cases' i with i ih; dsimp
  rcases x with ⟨_ | _, h⟩ <;> try rfl
  rw [List.length] at h
  rw [← h] at ih
  

Proof state:
case mk.mk.nil
n : ℕ
α : Type u_1
i : ℕ
ih✝ : i < n - 1
ih : i < 0 - 1
h✝ : List.length [] = n
h : 0 = n
⊢ get (tail { val := [], property := h✝ }) { val := i, isLt := ih✝ } =
    get { val := [], property := h✝ } { val := i + 1, isLt := (_ : i + 1 < n) }

Next tactic:
contradiction
@[simp]
theorem get_tail_succ : ∀ (v : Vector α n.succ) (i : Fin n), get (tail v) i = get v i.succ
  | ⟨a :: l, e⟩, ⟨i, h⟩ => by 

Proof state:
n : ℕ
α : Type u_1
a : α
l : List α
e : List.length (a :: l) = Nat.succ n
i : ℕ
h : i < n
⊢ get (tail { val := a :: l, property := e }) { val := i, isLt := h } =
    get { val := a :: l, property := e } (Fin.succ { val := i, isLt := h })

Next tactic:
simp [get_eq_get]
@[simp]
theorem get_tail_succ : ∀ (v : Vector α n.succ) (i : Fin n), get (tail v) i = get v i.succ
  | ⟨a :: l, e⟩, ⟨i, h⟩ => by simp [get_eq_get]; 

Proof state:
n : ℕ
α : Type u_1
a : α
l : List α
e : List.length (a :: l) = Nat.succ n
i : ℕ
h : i < n
⊢ List.get (toList (tail { val := a :: l, property := e }))
      { val := i, isLt := (_ : i < List.length (toList (tail { val := a :: l, property := e }))) } =
    List.get l { val := i, isLt := (_ : i < List.length l) }

Next tactic:
rfl
@[simp]
theorem tail_ofFn {n : ℕ} (f : Fin n.succ → α) : tail (ofFn f) = ofFn fun i => f i.succ :=
  (ofFn_get _).symm.trans <| by
    

Proof state:
n✝ : ℕ
α : Type u_1
n : ℕ
f : Fin (Nat.succ n) → α
⊢ ofFn (get (tail (ofFn f))) = ofFn fun i => f (Fin.succ i)

Next tactic:
congr
@[simp]
theorem tail_ofFn {n : ℕ} (f : Fin n.succ → α) : tail (ofFn f) = ofFn fun i => f i.succ :=
  (ofFn_get _).symm.trans <| by
    congr
    

Proof state:
case e_a
n✝ : ℕ
α : Type u_1
n : ℕ
f : Fin (Nat.succ n) → α
⊢ get (tail (ofFn f)) = fun i => f (Fin.succ i)

Next tactic:
funext i
@[simp]
theorem tail_ofFn {n : ℕ} (f : Fin n.succ → α) : tail (ofFn f) = ofFn fun i => f i.succ :=
  (ofFn_get _).symm.trans <| by
    congr
    funext i
    

Proof state:
case e_a.h
n✝ : ℕ
α : Type u_1
n : ℕ
f : Fin (Nat.succ n) → α
i : Fin (Nat.succ n - 1)
⊢ get (tail (ofFn f)) i = f (Fin.succ i)

Next tactic:
rw [get_tail, get_ofFn]
@[simp]
theorem tail_ofFn {n : ℕ} (f : Fin n.succ → α) : tail (ofFn f) = ofFn fun i => f i.succ :=
  (ofFn_get _).symm.trans <| by
    congr
    funext i
    rw [get_tail, get_ofFn]
    

Proof state:
case e_a.h
n✝ : ℕ
α : Type u_1
n : ℕ
f : Fin (Nat.succ n) → α
i : Fin (Nat.succ n - 1)
⊢ f { val := ↑i + 1, isLt := (_ : ↑i + 1 < Nat.succ n) } = f (Fin.succ i)

Next tactic:
rfl
/-- The list that makes up a `Vector` made up of a single element,
retrieved via `toList`, is equal to the list of that single element. -/
@[simp]
theorem toList_singleton (v : Vector α 1) : v.toList = [v.head] := by
  

Proof state:
n : ℕ
α : Type u_1
v : Vector α 1
⊢ toList v = [head v]

Next tactic:
rw [← v.cons_head_tail]
/-- The list that makes up a `Vector` made up of a single element,
retrieved via `toList`, is equal to the list of that single element. -/
@[simp]
theorem toList_singleton (v : Vector α 1) : v.toList = [v.head] := by
  rw [← v.cons_head_tail]
  

Proof state:
n : ℕ
α : Type u_1
v : Vector α 1
⊢ toList (head v ::ᵥ tail v) = [head (head v ::ᵥ tail v)]

Next tactic:
simp only [toList_cons, toList_nil, head_cons, eq_self_iff_true, and_self_iff, singleton_tail]
theorem not_empty_toList (v : Vector α (n + 1)) : ¬v.toList.isEmpty := by
  

Proof state:
n : ℕ
α : Type u_1
v : Vector α (n + 1)
⊢ ¬List.isEmpty (toList v) = true

Next tactic:
simp only [empty_toList_eq_ff, Bool.coe_sort_false, not_false_iff]
/-- Mapping under `id` does not change a vector. -/
@[simp]
theorem map_id {n : ℕ} (v : Vector α n) : Vector.map id v = v :=
  Vector.eq _ _ (by 

Proof state:
n✝ : ℕ
α : Type u_1
n : ℕ
v : Vector α n
⊢ toList (map id v) = toList v

Next tactic:
simp only [List.map_id, Vector.toList_map]
theorem nodup_iff_injective_get {v : Vector α n} : v.toList.Nodup ↔ Function.Injective v.get := by
  

Proof state:
n : ℕ
α : Type u_1
v : Vector α n
⊢ List.Nodup (toList v) ↔ Function.Injective (get v)

Next tactic:
cases' v with l hl