l3lab/ntp-mathlib huggingface dataset:
/-- The function that maps a solution `u` of `E` to its first
  `E.order` terms as a `LinearEquiv`. -/
def toInit : E.solSpace ≃ₗ[α] Fin E.order → α where
  toFun u x := (u : ℕ → α) x
  map_add' u v := by
    ext
    simp
  map_smul' a u := by
    ext
    simp
  invFun u := ⟨E.mkSol u, E.is_sol_mkSol u⟩
  left_inv u := by ext n; 

Proof state:
case a.h
α : Type u_1
inst✝ : CommSemiring α
E : LinearRecurrence α
u : ↥(solSpace E)
n : ℕ
⊢ ↑((fun u => { val := mkSol E u, property := (_ : IsSolution E (mkSol E u)) })
          (AddHom.toFun
            {
                toAddHom :=
                  { toFun := fun u x => ↑u ↑x,
                    map_add' :=
                      (_ :
                        ∀ (u v : ↥(solSpace E)),
                          (fun u x => ↑u ↑x) (u + v) = (fun u x => ↑u ↑x) u + (fun u x => ↑u ↑x) v) },
                map_smul' :=
                  (_ :
                    ∀ (a : α) (u : ↥(solSpace E)),
                      AddHom.toFun
                          { toFun := fun u x => ↑u ↑x,
                            map_add' :=
                              (_ :
                                ∀ (u v : ↥(solSpace E)),
                                  (fun u x => ↑u ↑x) (u + v) = (fun u x => ↑u ↑x) u + (fun u x => ↑u ↑x) v) }
                          (a • u) =
                        (RingHom.id α) a •
                          AddHom.toFun
                            { toFun := fun u x => ↑u ↑x,
                              map_add' :=
                                (_ :
                                  ∀ (u v : ↥(solSpace E)),
                                    (fun u x => ↑u ↑x) (u + v) = (fun u x => ↑u ↑x) u + (fun u x => ↑u ↑x) v) }
                            u) }.toAddHom
            u))
      n =
    ↑u n

Next tactic:
symm
/-- The function that maps a solution `u` of `E` to its first
  `E.order` terms as a `LinearEquiv`. -/
def toInit : E.solSpace ≃ₗ[α] Fin E.order → α where
  toFun u x := (u : ℕ → α) x
  map_add' u v := by
    ext
    simp
  map_smul' a u := by
    ext
    simp
  invFun u := ⟨E.mkSol u, E.is_sol_mkSol u⟩
  left_inv u := by ext n; symm; 

Proof state:
case a.h
α : Type u_1
inst✝ : CommSemiring α
E : LinearRecurrence α
u : ↥(solSpace E)
n : ℕ
⊢ ↑u n =
    ↑((fun u => { val := mkSol E u, property := (_ : IsSolution E (mkSol E u)) })
          (AddHom.toFun
            {
                toAddHom :=
                  { toFun := fun u x => ↑u ↑x,
                    map_add' :=
                      (_ :
                        ∀ (u v : ↥(solSpace E)),
                          (fun u x => ↑u ↑x) (u + v) = (fun u x => ↑u ↑x) u + (fun u x => ↑u ↑x) v) },
                map_smul' :=
                  (_ :
                    ∀ (a : α) (u : ↥(solSpace E)),
                      AddHom.toFun
                          { toFun := fun u x => ↑u ↑x,
                            map_add' :=
                              (_ :
                                ∀ (u v : ↥(solSpace E)),
                                  (fun u x => ↑u ↑x) (u + v) = (fun u x => ↑u ↑x) u + (fun u x => ↑u ↑x) v) }
                          (a • u) =
                        (RingHom.id α) a •
                          AddHom.toFun
                            { toFun := fun u x => ↑u ↑x,
                              map_add' :=
                                (_ :
                                  ∀ (u v : ↥(solSpace E)),
                                    (fun u x => ↑u ↑x) (u + v) = (fun u x => ↑u ↑x) u + (fun u x => ↑u ↑x) v) }
                            u) }.toAddHom
            u))
      n

Next tactic:
apply E.eq_mk_of_is_sol_of_eq_init u.2
/-- The function that maps a solution `u` of `E` to its first
  `E.order` terms as a `LinearEquiv`. -/
def toInit : E.solSpace ≃ₗ[α] Fin E.order → α where
  toFun u x := (u : ℕ → α) x
  map_add' u v := by
    ext
    simp
  map_smul' a u := by
    ext
    simp
  invFun u := ⟨E.mkSol u, E.is_sol_mkSol u⟩
  left_inv u := by ext n; symm; apply E.eq_mk_of_is_sol_of_eq_init u.2; 

Proof state:
case a.h.heq
α : Type u_1
inst✝ : CommSemiring α
E : LinearRecurrence α
u : ↥(solSpace E)
n : ℕ
⊢ ∀ (n : Fin E.order),
    ↑u ↑n =
      AddHom.toFun
        {
            toAddHom :=
              { toFun := fun u x => ↑u ↑x,
                map_add' :=
                  (_ :
                    ∀ (u v : ↥(solSpace E)),
                      (fun u x => ↑u ↑x) (u + v) = (fun u x => ↑u ↑x) u + (fun u x => ↑u ↑x) v) },
            map_smul' :=
              (_ :
                ∀ (a : α) (u : ↥(solSpace E)),
                  AddHom.toFun
                      { toFun := fun u x => ↑u ↑x,
                        map_add' :=
                          (_ :
                            ∀ (u v : ↥(solSpace E)),
                              (fun u x => ↑u ↑x) (u + v) = (fun u x => ↑u ↑x) u + (fun u x => ↑u ↑x) v) }
                      (a • u) =
                    (RingHom.id α) a •
                      AddHom.toFun
                        { toFun := fun u x => ↑u ↑x,
                          map_add' :=
                            (_ :
                              ∀ (u v : ↥(solSpace E)),
                                (fun u x => ↑u ↑x) (u + v) = (fun u x => ↑u ↑x) u + (fun u x => ↑u ↑x) v) }
                        u) }.toAddHom
        u n

Next tactic:
intro k
/-- The function that maps a solution `u` of `E` to its first
  `E.order` terms as a `LinearEquiv`. -/
def toInit : E.solSpace ≃ₗ[α] Fin E.order → α where
  toFun u x := (u : ℕ → α) x
  map_add' u v := by
    ext
    simp
  map_smul' a u := by
    ext
    simp
  invFun u := ⟨E.mkSol u, E.is_sol_mkSol u⟩
  left_inv u := by ext n; symm; apply E.eq_mk_of_is_sol_of_eq_init u.2; intro k; 

Proof state:
case a.h.heq
α : Type u_1
inst✝ : CommSemiring α
E : LinearRecurrence α
u : ↥(solSpace E)
n : ℕ
k : Fin E.order
⊢ ↑u ↑k =
    AddHom.toFun
      {
          toAddHom :=
            { toFun := fun u x => ↑u ↑x,
              map_add' :=
                (_ :
                  ∀ (u v : ↥(solSpace E)), (fun u x => ↑u ↑x) (u + v) = (fun u x => ↑u ↑x) u + (fun u x => ↑u ↑x) v) },
          map_smul' :=
            (_ :
              ∀ (a : α) (u : ↥(solSpace E)),
                AddHom.toFun
                    { toFun := fun u x => ↑u ↑x,
                      map_add' :=
                        (_ :
                          ∀ (u v : ↥(solSpace E)),
                            (fun u x => ↑u ↑x) (u + v) = (fun u x => ↑u ↑x) u + (fun u x => ↑u ↑x) v) }
                    (a • u) =
                  (RingHom.id α) a •
                    AddHom.toFun
                      { toFun := fun u x => ↑u ↑x,
                        map_add' :=
                          (_ :
                            ∀ (u v : ↥(solSpace E)),
                              (fun u x => ↑u ↑x) (u + v) = (fun u x => ↑u ↑x) u + (fun u x => ↑u ↑x) v) }
                      u) }.toAddHom
      u k

Next tactic:
rfl
/-- Two solutions are equal iff they are equal on `range E.order`. -/
theorem sol_eq_of_eq_init (u v : ℕ → α) (hu : E.IsSolution u) (hv : E.IsSolution v) :
    u = v ↔ Set.EqOn u v ↑(range E.order) := by
  

Proof state:
α : Type u_1
inst✝ : CommSemiring α
E : LinearRecurrence α
u v : ℕ → α
hu : IsSolution E u
hv : IsSolution E v
⊢ u = v ↔ Set.EqOn u v ↑(range E.order)

Next tactic:
refine' Iff.intro (fun h x _ ↦ h ▸ rfl) _
/-- Two solutions are equal iff they are equal on `range E.order`. -/
theorem sol_eq_of_eq_init (u v : ℕ → α) (hu : E.IsSolution u) (hv : E.IsSolution v) :
    u = v ↔ Set.EqOn u v ↑(range E.order) := by
  refine' Iff.intro (fun h x _ ↦ h ▸ rfl) _
  

Proof state:
α : Type u_1
inst✝ : CommSemiring α
E : LinearRecurrence α
u v : ℕ → α
hu : IsSolution E u
hv : IsSolution E v
⊢ Set.EqOn u v ↑(range E.order) → u = v

Next tactic:
intro h
/-- Two solutions are equal iff they are equal on `range E.order`. -/
theorem sol_eq_of_eq_init (u v : ℕ → α) (hu : E.IsSolution u) (hv : E.IsSolution v) :
    u = v ↔ Set.EqOn u v ↑(range E.order) := by
  refine' Iff.intro (fun h x _ ↦ h ▸ rfl) _
  intro h
  

Proof state:
α : Type u_1
inst✝ : CommSemiring α
E : LinearRecurrence α
u v : ℕ → α
hu : IsSolution E u
hv : IsSolution E v
h : Set.EqOn u v ↑(range E.order)
⊢ u = v

Next tactic:
set u' : ↥E.solSpace := ⟨u, hu⟩
/-- Two solutions are equal iff they are equal on `range E.order`. -/
theorem sol_eq_of_eq_init (u v : ℕ → α) (hu : E.IsSolution u) (hv : E.IsSolution v) :
    u = v ↔ Set.EqOn u v ↑(range E.order) := by
  refine' Iff.intro (fun h x _ ↦ h ▸ rfl) _
  intro h
  set u' : ↥E.solSpace := ⟨u, hu⟩
  

Proof state:
α : Type u_1
inst✝ : CommSemiring α
E : LinearRecurrence α
u v : ℕ → α
hu : IsSolution E u
hv : IsSolution E v
h : Set.EqOn u v ↑(range E.order)
u' : ↥(solSpace E) := { val := u, property := hu }
⊢ u = v

Next tactic:
set v' : ↥E.solSpace := ⟨v, hv⟩
/-- Two solutions are equal iff they are equal on `range E.order`. -/
theorem sol_eq_of_eq_init (u v : ℕ → α) (hu : E.IsSolution u) (hv : E.IsSolution v) :
    u = v ↔ Set.EqOn u v ↑(range E.order) := by
  refine' Iff.intro (fun h x _ ↦ h ▸ rfl) _
  intro h
  set u' : ↥E.solSpace := ⟨u, hu⟩
  set v' : ↥E.solSpace := ⟨v, hv⟩
  

Proof state:
α : Type u_1
inst✝ : CommSemiring α
E : LinearRecurrence α
u v : ℕ → α
hu : IsSolution E u
hv : IsSolution E v
h : Set.EqOn u v ↑(range E.order)
u' : ↥(solSpace E) := { val := u, property := hu }
v' : ↥(solSpace E) := { val := v, property := hv }
⊢ u = v

Next tactic:
change u'.val = v'.val
/-- Two solutions are equal iff they are equal on `range E.order`. -/
theorem sol_eq_of_eq_init (u v : ℕ → α) (hu : E.IsSolution u) (hv : E.IsSolution v) :
    u = v ↔ Set.EqOn u v ↑(range E.order) := by
  refine' Iff.intro (fun h x _ ↦ h ▸ rfl) _
  intro h
  set u' : ↥E.solSpace := ⟨u, hu⟩
  set v' : ↥E.solSpace := ⟨v, hv⟩
  change u'.val = v'.val
  

Proof state:
α : Type u_1
inst✝ : CommSemiring α
E : LinearRecurrence α
u v : ℕ → α
hu : IsSolution E u
hv : IsSolution E v
h : Set.EqOn u v ↑(range E.order)
u' : ↥(solSpace E) := { val := u, property := hu }
v' : ↥(solSpace E) := { val := v, property := hv }
⊢ ↑u' = ↑v'

Next tactic:
suffices h' : u' = v'
/-- Two solutions are equal iff they are equal on `range E.order`. -/
theorem sol_eq_of_eq_init (u v : ℕ → α) (hu : E.IsSolution u) (hv : E.IsSolution v) :
    u = v ↔ Set.EqOn u v ↑(range E.order) := by
  refine' Iff.intro (fun h x _ ↦ h ▸ rfl) _
  intro h
  set u' : ↥E.solSpace := ⟨u, hu⟩
  set v' : ↥E.solSpace := ⟨v, hv⟩
  change u'.val = v'.val
  suffices h' : u' = v'; 

Proof state:
α : Type u_1
inst✝ : CommSemiring α
E : LinearRecurrence α
u v : ℕ → α
hu : IsSolution E u
hv : IsSolution E v
h : Set.EqOn u v ↑(range E.order)
u' : ↥(solSpace E) := { val := u, property := hu }
v' : ↥(solSpace E) := { val := v, property := hv }
h' : u' = v'
⊢ ↑u' = ↑v'
case h'
α : Type u_1
inst✝ : CommSemiring α
E : LinearRecurrence α
u v : ℕ → α
hu : IsSolution E u
hv : IsSolution E v
h : Set.EqOn u v ↑(range E.order)
u' : ↥(solSpace E) := { val := u, property := hu }
v' : ↥(solSpace E) := { val := v, property := hv }
⊢ u' = v'

Next tactic:
exact h' ▸ rfl
/-- Two solutions are equal iff they are equal on `range E.order`. -/
theorem sol_eq_of_eq_init (u v : ℕ → α) (hu : E.IsSolution u) (hv : E.IsSolution v) :
    u = v ↔ Set.EqOn u v ↑(range E.order) := by
  refine' Iff.intro (fun h x _ ↦ h ▸ rfl) _
  intro h
  set u' : ↥E.solSpace := ⟨u, hu⟩
  set v' : ↥E.solSpace := ⟨v, hv⟩
  change u'.val = v'.val
  suffices h' : u' = v'; exact h' ▸ rfl
  

Proof state:
case h'
α : Type u_1
inst✝ : CommSemiring α
E : LinearRecurrence α
u v : ℕ → α
hu : IsSolution E u
hv : IsSolution E v
h : Set.EqOn u v ↑(range E.order)
u' : ↥(solSpace E) := { val := u, property := hu }
v' : ↥(solSpace E) := { val := v, property := hv }
⊢ u' = v'

Next tactic:
rw [← E.toInit.toEquiv.apply_eq_iff_eq, LinearEquiv.coe_toEquiv]
/-- Two solutions are equal iff they are equal on `range E.order`. -/
theorem sol_eq_of_eq_init (u v : ℕ → α) (hu : E.IsSolution u) (hv : E.IsSolution v) :
    u = v ↔ Set.EqOn u v ↑(range E.order) := by
  refine' Iff.intro (fun h x _ ↦ h ▸ rfl) _
  intro h
  set u' : ↥E.solSpace := ⟨u, hu⟩
  set v' : ↥E.solSpace := ⟨v, hv⟩
  change u'.val = v'.val
  suffices h' : u' = v'; exact h' ▸ rfl
  rw [← E.toInit.toEquiv.apply_eq_iff_eq, LinearEquiv.coe_toEquiv]
  

Proof state:
case h'
α : Type u_1
inst✝ : CommSemiring α
E : LinearRecurrence α
u v : ℕ → α
hu : IsSolution E u
hv : IsSolution E v
h : Set.EqOn u v ↑(range E.order)
u' : ↥(solSpace E) := { val := u, property := hu }
v' : ↥(solSpace E) := { val := v, property := hv }
⊢ (toInit E) u' = (toInit E) v'

Next tactic:
ext x
/-- Two solutions are equal iff they are equal on `range E.order`. -/
theorem sol_eq_of_eq_init (u v : ℕ → α) (hu : E.IsSolution u) (hv : E.IsSolution v) :
    u = v ↔ Set.EqOn u v ↑(range E.order) := by
  refine' Iff.intro (fun h x _ ↦ h ▸ rfl) _
  intro h
  set u' : ↥E.solSpace := ⟨u, hu⟩
  set v' : ↥E.solSpace := ⟨v, hv⟩
  change u'.val = v'.val
  suffices h' : u' = v'; exact h' ▸ rfl
  rw [← E.toInit.toEquiv.apply_eq_iff_eq, LinearEquiv.coe_toEquiv]
  ext x
  

Proof state:
case h'.h
α : Type u_1
inst✝ : CommSemiring α
E : LinearRecurrence α
u v : ℕ → α
hu : IsSolution E u
hv : IsSolution E v
h : Set.EqOn u v ↑(range E.order)
u' : ↥(solSpace E) := { val := u, property := hu }
v' : ↥(solSpace E) := { val := v, property := hv }
x : Fin E.order
⊢ (toInit E) u' x = (toInit E) v' x

Next tactic:
exact mod_cast h (mem_range.mpr x.2)
/-- `E.tupleSucc` maps `![s₀, s₁, ..., sₙ]` to `![s₁, ..., sₙ, ∑ (E.coeffs i) * sᵢ]`,
  where `n := E.order`. -/
def tupleSucc : (Fin E.order → α) →ₗ[α] Fin E.order → α where
  toFun X i := if h : (i : ℕ) + 1 < E.order then X ⟨i + 1, h⟩ else ∑ i, E.coeffs i * X i
  map_add' x y := by
    

Proof state:
α : Type u_1
inst✝ : CommSemiring α
E : LinearRecurrence α
x y : Fin E.order → α
⊢ (fun X i => if h : ↑i + 1 < E.order then X { val := ↑i + 1, isLt := h } else ∑ i : Fin E.order, coeffs E i * X i)
      (x + y) =
    (fun X i => if h : ↑i + 1 < E.order then X { val := ↑i + 1, isLt := h } else ∑ i : Fin E.order, coeffs E i * X i)
        x +
      (fun X i => if h : ↑i + 1 < E.order then X { val := ↑i + 1, isLt := h } else ∑ i : Fin E.order, coeffs E i * X i)
        y

Next tactic:
ext i
/-- `E.tupleSucc` maps `![s₀, s₁, ..., sₙ]` to `![s₁, ..., sₙ, ∑ (E.coeffs i) * sᵢ]`,
  where `n := E.order`. -/
def tupleSucc : (Fin E.order → α) →ₗ[α] Fin E.order → α where
  toFun X i := if h : (i : ℕ) + 1 < E.order then X ⟨i + 1, h⟩ else ∑ i, E.coeffs i * X i
  map_add' x y := by
    ext i
    

Proof state:
case h
α : Type u_1
inst✝ : CommSemiring α
E : LinearRecurrence α
x y : Fin E.order → α
i : Fin E.order
⊢ (fun X i => if h : ↑i + 1 < E.order then X { val := ↑i + 1, isLt := h } else ∑ i : Fin E.order, coeffs E i * X i)
      (x + y) i =
    ((fun X i => if h : ↑i + 1 < E.order then X { val := ↑i + 1, isLt := h } else ∑ i : Fin E.order, coeffs E i * X i)
          x +
        (fun X i =>
            if h : ↑i + 1 < E.order then X { val := ↑i + 1, isLt := h } else ∑ i : Fin E.order, coeffs E i * X i)
          y)
      i

Next tactic:
simp only
/-- `E.tupleSucc` maps `![s₀, s₁, ..., sₙ]` to `![s₁, ..., sₙ, ∑ (E.coeffs i) * sᵢ]`,
  where `n := E.order`. -/
def tupleSucc : (Fin E.order → α) →ₗ[α] Fin E.order → α where
  toFun X i := if h : (i : ℕ) + 1 < E.order then X ⟨i + 1, h⟩ else ∑ i, E.coeffs i * X i
  map_add' x y := by
    ext i
    simp only
    

Proof state:
case h
α : Type u_1
inst✝ : CommSemiring α
E : LinearRecurrence α
x y : Fin E.order → α
i : Fin E.order
⊢ (if h : ↑i + 1 < E.order then (x + y) { val := ↑i + 1, isLt := h } else ∑ i : Fin E.order, coeffs E i * (x + y) i) =
    ((fun i => if h : ↑i + 1 < E.order then x { val := ↑i + 1, isLt := h } else ∑ i : Fin E.order, coeffs E i * x i) +
        fun i => if h : ↑i + 1 < E.order then y { val := ↑i + 1, isLt := h } else ∑ i : Fin E.order, coeffs E i * y i)
      i

Next tactic:
split_ifs with h
/-- `E.tupleSucc` maps `![s₀, s₁, ..., sₙ]` to `![s₁, ..., sₙ, ∑ (E.coeffs i) * sᵢ]`,
  where `n := E.order`. -/
def tupleSucc : (Fin E.order → α) →ₗ[α] Fin E.order → α where
  toFun X i := if h : (i : ℕ) + 1 < E.order then X ⟨i + 1, h⟩ else ∑ i, E.coeffs i * X i
  map_add' x y := by
    ext i
    simp only
    split_ifs with h <;> 

Proof state:
case pos
α : Type u_1
inst✝ : CommSemiring α
E : LinearRecurrence α
x y : Fin E.order → α
i : Fin E.order
h : ↑i + 1 < E.order
⊢ (x + y) { val := ↑i + 1, isLt := h } =
    ((fun i => if h : ↑i + 1 < E.order then x { val := ↑i + 1, isLt := h } else ∑ i : Fin E.order, coeffs E i * x i) +
        fun i => if h : ↑i + 1 < E.order then y { val := ↑i + 1, isLt := h } else ∑ i : Fin E.order, coeffs E i * y i)
      i

Next tactic:
simp [h, mul_add, sum_add_distrib]
/-- `E.tupleSucc` maps `![s₀, s₁, ..., sₙ]` to `![s₁, ..., sₙ, ∑ (E.coeffs i) * sᵢ]`,
  where `n := E.order`. -/
def tupleSucc : (Fin E.order → α) →ₗ[α] Fin E.order → α where
  toFun X i := if h : (i : ℕ) + 1 < E.order then X ⟨i + 1, h⟩ else ∑ i, E.coeffs i * X i
  map_add' x y := by
    ext i
    simp only
    split_ifs with h <;> 

Proof state:
case neg
α : Type u_1
inst✝ : CommSemiring α
E : LinearRecurrence α
x y : Fin E.order → α
i : Fin E.order
h : ¬↑i + 1 < E.order
⊢ ∑ i : Fin E.order, coeffs E i * (x + y) i =
    ((fun i => if h : ↑i + 1 < E.order then x { val := ↑i + 1, isLt := h } else ∑ i : Fin E.order, coeffs E i * x i) +
        fun i => if h : ↑i + 1 < E.order then y { val := ↑i + 1, isLt := h } else ∑ i : Fin E.order, coeffs E i * y i)
      i

Next tactic:
simp [h, mul_add, sum_add_distrib]
/-- `E.tupleSucc` maps `![s₀, s₁, ..., sₙ]` to `![s₁, ..., sₙ, ∑ (E.coeffs i) * sᵢ]`,
  where `n := E.order`. -/
def tupleSucc : (Fin E.order → α) →ₗ[α] Fin E.order → α where
  toFun X i := if h : (i : ℕ) + 1 < E.order then X ⟨i + 1, h⟩ else ∑ i, E.coeffs i * X i
  map_add' x y := by
    ext i
    simp only
    split_ifs with h <;> simp [h, mul_add, sum_add_distrib]
  map_smul' x y := by
    

Proof state:
α : Type u_1
inst✝ : CommSemiring α
E : LinearRecurrence α
x : α
y : Fin E.order → α
⊢ AddHom.toFun
      {
        toFun := fun X i =>
          if h : ↑i + 1 < E.order then X { val := ↑i + 1, isLt := h } else ∑ i : Fin E.order, coeffs E i * X i,
        map_add' :=
          (_ :
            ∀ (x y : Fin E.order → α),
              (fun X i =>
                    if h : ↑i + 1 < E.order then X { val := ↑i + 1, isLt := h }
                    else ∑ i : Fin E.order, coeffs E i * X i)
                  (x + y) =
                (fun X i =>
                      if h : ↑i + 1 < E.order then X { val := ↑i + 1, isLt := h }
                      else ∑ i : Fin E.order, coeffs E i * X i)
                    x +
                  (fun X i =>
                      if h : ↑i + 1 < E.order then X { val := ↑i + 1, isLt := h }
                      else ∑ i : Fin E.order, coeffs E i * X i)
                    y) }
      (x • y) =
    (RingHom.id α) x •
      AddHom.toFun
        {
          toFun := fun X i =>
            if h : ↑i + 1 < E.order then X { val := ↑i + 1, isLt := h } else ∑ i : Fin E.order, coeffs E i * X i,
          map_add' :=
            (_ :
              ∀ (x y : Fin E.order → α),
                (fun X i =>
                      if h : ↑i + 1 < E.order then X { val := ↑i + 1, isLt := h }
                      else ∑ i : Fin E.order, coeffs E i * X i)
                    (x + y) =
                  (fun X i =>
                        if h : ↑i + 1 < E.order then X { val := ↑i + 1, isLt := h }
                        else ∑ i : Fin E.order, coeffs E i * X i)
                      x +
                    (fun X i =>
                        if h : ↑i + 1 < E.order then X { val := ↑i + 1, isLt := h }
                        else ∑ i : Fin E.order, coeffs E i * X i)
                      y) }
        y

Next tactic:
ext i
/-- `E.tupleSucc` maps `![s₀, s₁, ..., sₙ]` to `![s₁, ..., sₙ, ∑ (E.coeffs i) * sᵢ]`,
  where `n := E.order`. -/
def tupleSucc : (Fin E.order → α) →ₗ[α] Fin E.order → α where
  toFun X i := if h : (i : ℕ) + 1 < E.order then X ⟨i + 1, h⟩ else ∑ i, E.coeffs i * X i
  map_add' x y := by
    ext i
    simp only
    split_ifs with h <;> simp [h, mul_add, sum_add_distrib]
  map_smul' x y := by
    ext i
    

Proof state:
case h
α : Type u_1
inst✝ : CommSemiring α
E : LinearRecurrence α
x : α
y : Fin E.order → α
i : Fin E.order
⊢ AddHom.toFun
      {
        toFun := fun X i =>
          if h : ↑i + 1 < E.order then X { val := ↑i + 1, isLt := h } else ∑ i : Fin E.order, coeffs E i * X i,
        map_add' :=
          (_ :
            ∀ (x y : Fin E.order → α),
              (fun X i =>
                    if h : ↑i + 1 < E.order then X { val := ↑i + 1, isLt := h }
                    else ∑ i : Fin E.order, coeffs E i * X i)
                  (x + y) =
                (fun X i =>
                      if h : ↑i + 1 < E.order then X { val := ↑i + 1, isLt := h }
                      else ∑ i : Fin E.order, coeffs E i * X i)
                    x +
                  (fun X i =>
                      if h : ↑i + 1 < E.order then X { val := ↑i + 1, isLt := h }
                      else ∑ i : Fin E.order, coeffs E i * X i)
                    y) }
      (x • y) i =
    ((RingHom.id α) x •
        AddHom.toFun
          {
            toFun := fun X i =>
              if h : ↑i + 1 < E.order then X { val := ↑i + 1, isLt := h } else ∑ i : Fin E.order, coeffs E i * X i,
            map_add' :=
              (_ :
                ∀ (x y : Fin E.order → α),
                  (fun X i =>
                        if h : ↑i + 1 < E.order then X { val := ↑i + 1, isLt := h }
                        else ∑ i : Fin E.order, coeffs E i * X i)
                      (x + y) =
                    (fun X i =>
                          if h : ↑i + 1 < E.order then X { val := ↑i + 1, isLt := h }
                          else ∑ i : Fin E.order, coeffs E i * X i)
                        x +
                      (fun X i =>
                          if h : ↑i + 1 < E.order then X { val := ↑i + 1, isLt := h }
                          else ∑ i : Fin E.order, coeffs E i * X i)
                        y) }
          y)
      i

Next tactic:
simp only
/-- `E.tupleSucc` maps `![s₀, s₁, ..., sₙ]` to `![s₁, ..., sₙ, ∑ (E.coeffs i) * sᵢ]`,
  where `n := E.order`. -/
def tupleSucc : (Fin E.order → α) →ₗ[α] Fin E.order → α where
  toFun X i := if h : (i : ℕ) + 1 < E.order then X ⟨i + 1, h⟩ else ∑ i, E.coeffs i * X i
  map_add' x y := by
    ext i
    simp only
    split_ifs with h <;> simp [h, mul_add, sum_add_distrib]
  map_smul' x y := by
    ext i
    simp only
    

Proof state:
case h
α : Type u_1
inst✝ : CommSemiring α
E : LinearRecurrence α
x : α
y : Fin E.order → α
i : Fin E.order
⊢ (if h : ↑i + 1 < E.order then (x • y) { val := ↑i + 1, isLt := h } else ∑ i : Fin E.order, coeffs E i * (x • y) i) =
    ((RingHom.id α) x • fun i =>
        if h : ↑i + 1 < E.order then y { val := ↑i + 1, isLt := h } else ∑ i : Fin E.order, coeffs E i * y i)
      i

Next tactic:
split_ifs with h
/-- `E.tupleSucc` maps `![s₀, s₁, ..., sₙ]` to `![s₁, ..., sₙ, ∑ (E.coeffs i) * sᵢ]`,
  where `n := E.order`. -/
def tupleSucc : (Fin E.order → α) →ₗ[α] Fin E.order → α where
  toFun X i := if h : (i : ℕ) + 1 < E.order then X ⟨i + 1, h⟩ else ∑ i, E.coeffs i * X i
  map_add' x y := by
    ext i
    simp only
    split_ifs with h <;> simp [h, mul_add, sum_add_distrib]
  map_smul' x y := by
    ext i
    simp only
    split_ifs with h <;> 

Proof state:
case pos
α : Type u_1
inst✝ : CommSemiring α
E : LinearRecurrence α
x : α
y : Fin E.order → α
i : Fin E.order
h : ↑i + 1 < E.order
⊢ (x • y) { val := ↑i + 1, isLt := h } =
    ((RingHom.id α) x • fun i =>
        if h : ↑i + 1 < E.order then y { val := ↑i + 1, isLt := h } else ∑ i : Fin E.order, coeffs E i * y i)
      i

Next tactic:
simp [h, mul_sum]